skip to Main Content

So I’m making a small personal library app using mongoDB, flask and Python where you can input the entries for your books and keep them in a sort of account/login.
The issue is, I can’t get the form itself to ping the function to edit things. I know I’m targeting wrong, but I feel like I’m at a point where I need someone to explain like I’m five where I’m going wrong.

So this is the function:

@app.route("/profile/<username>", methods=["GET", "POST"])
def edit_book(book_id, username):
    if request.method == "POST":
        submit = {
            "category_name": request.form.get("category_name"),
            "title": request.form.get("title"),
            "author": request.form.get("author"),
            "genre": request.form.get("genre"),
            "rating": request.form.get("rating"),
            "release_date": request.form.get("release_date"),
            "publisher": request.form.get("publisher"),
            "page_count": request.form.get("page_count"),
            "isbn": request.form.get("isbn")
        }
        mongo.db.booksread.update_one({"_id": ObjectId(book_id)}, submit)
        mongo.db.bookstoberead.update_one({"_id": ObjectId(book_id)}, submit)
        flash("Book Entry Edited")

    unreadbooks = mongo.db.bookstoberead.find_one({"_id": ObjectId(book_id)})
    books = mongo.db.booksread.find_one({"_id": ObjectId(book_id)})
    categories = mongo.db.reading_list.find().sort("category_name", 1)

    return redirect(url_for("profile", booksread=books, readinglist=categories, bookstoberead=unreadbooks))

and this is the post action linked with it:

<form class="col s12" method="POST" action="{{ url_for('edit_book', book_id=book_id, username=username) }}">

The repos is here(Personal Library App), and the app with all of the functions is under "app.py", and the page that the form is linked on is "profile.html" under the templates folder.

Live preview is On Heroku, if that helps to see where things are linked together. You can use the username/password of Tester/Tester1 for access.

I’ve tried passing different arguments in for the post action, function and the route. I don’t know if I’m passing the wrong arguments in or if there are instances I’ve missed, I’m still very very hazy on arguments as it is.
I’ve tried to make heads or tails of some documentation, but something just isn’t clicking.

Any and every piece of help is absolutely appreciated.

2

Answers


  1. Chosen as BEST ANSWER

    So, I figured it out. The post action needed to be "book_id=book._id" instead as I'm targeting the ID of the database entry. The second issue was that on the redirect, I wasn't targeting a session. The records are locked behind a logged in profile, so I needed to target the logged in session in order for it to go anywhere. All fixed.


  2. In Flask, you can add variables to your Route that will then be passed to the view function as keyword arguments. In your example, you define a method with two arguments book_id and username. But in your route, you only define the username as a variable @app.route("/profile/<username>", ...).

    This would lead to a Type error when flask tries to call your method with only the username.

    Because you have not posted the error message, I can only assume that something like the following is raised.
    TypeError: edit_book() missing 1 required positional argument: 'book_id'

    The URL generated by the url_for('edit_book', book_id=book_id, username=username) method will not raise any errors and build a URL like profile/exampleuser?book_id=99 with all unknown parameters as query parameters.

    As a fix you could simply add the book_id as a second route variable.

    @app.route("/profile/<username>/<book_id>", methods=["GET", "POST"])
    def edit_book(book_id, username):
    

    For additional information, view:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search