Search code examples
pythonflaskhttp-redirectpostback

redirect() / render_template() enters the route once again when called from the same route in Flask


I have created a wishlist page which lists the items wishlisted by a user. The user can remove any item from the wishlist by clicking on the Remove button. On clicking the remove button, the HTML <form> submits it to the back-end application. The back-end application then removes the item from the wishlist database and redirects back to the same page using return redirect(url_for('wishlist')).

The problem I am facing is that if the user goes back after removing the item from the wishlist he has to go back twice to reach the page from where the user came from. This is caused due to the redirect that I am performing after removing the item which is necessary to show the updated wishlist.

I have also tried render_template() instead of redirect() but it is also causing the same problem.

Code for back-end:

@app.route('/wishlist/',methods=['GET','POST'])
@login_required
def wishlist():

    userid=current_user.get_id()

    if request.method=='POST':
        toRemove=request.form['remove']
        deleteWish=session.query(Wishlist).filter_by(userId=userid,productId=toRemove).one()
        session.delete(deleteWish)
        session.commit()
        return redirect(url_for('wishlist'))

    subquery=session.query(Wishlist.productId).filter(Wishlist.userId==userid).subquery()
    wishes=session.query(Products).filter(Products.id.in_(subquery))

    return render_template("wishlist.html",wishes=wishes)

HTML:

<html>

<body>

    {% for wish in wishes %}
        <img src={{wish.image_path}} width="150" height="200">
        </br>
        {{wish.material}}
        {{wish.productType}}
        </br>
        {{wish.price}}
        </br>
        <form action="{{url_for('wishlist')}}" method="POST" target="_self">
            <button name="remove" type="submit" value="{{wish.id}}">Remove</button>
        </form>
        </br>
    {% endfor %}
</body>
</html>

Please suggest me a way to prevent this.


Solution

  • You may want to create a different end point for deleting wishes. This endpoint then redirects to your wish list once deletion is done.

    FLASK

    @app.route('/wishlist/',methods=['GET','POST'])
    @login_required
    userid=current_user.get_id()
    def wishlist():
     subquery=session.query(Wishlist.productId).filter(Wishlist.userId==userid).subquery()
        wishes=session.query(Products).filter(Products.id.in_(subquery))
        return render_template("wishlist.html")
    
    @app.route('/deletewish', methods = ['GET', 'POST']
    def deletewish():
    if request.method=='POST':
        toRemove=request.form['wish_delete_id']    
        deleteWish=...
        session.delete(deleteWish)
        session.commit()
        return redirect(url_for('wishlist'))
    

    HTML

    <html>
    
    <body>
    {% for wish in wishes %}
            <img src={{wish.image_path}} width="150" height="200">
            </br>
            {{wish.material}}
            {{wish.productType}}
            </br>
            {{wish.price}}
            </br>
            <form method="POST" target="_self">
                <button class="remove_wish" type="submit" value={{wish.id}}>Remove</button>
            </form>
        </br>
    {% endfor %}`
    <script src='path_to_jquery.js'></script>
    <script src='path_to_deletewish.js'></script>
    </body>
    </html>
    

    JS //deletewish.js content

    <script>
    $(document).ready(function() {
        $('.remove_wish').click(function (event) {
         event.preventDefault();
        $.ajax({
        data : {
                wish_delete_id : $(this).val();
                },
            type : 'POST',
            url : '/deletewish',
            success: function (data) {
                location.reload();
            },
            error: function (e) {
                alert('something went wrong')
            }
        });
    });
    })
    </script>