I'm coding a simple todo list app in Flask for study. My todo model has title, description and a check attribute. When false is a "to do" task, and when the user click on a checkbox it will change to "true", so that task was done. That said, my current PATCH route can handle the title, description and check change, all in one.
So now I was thinking: in my frontend, I'll create the checkbox and when it's clicked the client will send a PATCH request with just the check value; for description and title, I'll create a "edit", so the user can edit those two and when its done he can click in a "save" button, when its clicked the client will send a PATCH request with title and/or description changes.
I realized that there's no way to a request with changes on all the three (title, description and check) could be made, check will be always working alone.
This is my PATCH code:
@app.route("/todo/update/<id>", methods=["PATCH"])
def update_todo(id):
updated_todo = db.session.execute(db.select(Todo).filter_by(id=id)).scalar_one()
if "check" in request.json:
updated_todo.check = request.json["check"]
if "title" in request.json:
updated_todo.title = request.json["title"]
if "description" in request.json:
updated_todo.description = request.json["description"]
db.sessionmit()
return "", 204
Since I'm using if to know what's changing, could I create a new PATCH route just for check and let it work alone? Since I don't need to verify if check is in a title/description PATCH request (it never will be anyway), it'll be a little faster in theory, right? Is there any conceptual or convention problem around it?
It would be something like this:
@app.route("/todo/update/<id>", methods=["PATCH"])
def update_todo(id):
updated_todo = db.session.execute(db.select(Todo).filter_by(id=id)).scalar_one()
if "title" in request.json:
updated_todo.title = request.json["title"]
if "description" in request.json:
updated_todo.description = request.json["description"]
db.sessionmit()
return "", 204
@app.route("/todo/update/check/<id>", methods=["PATCH"])
def update_todo(id):
updated_todo = db.session.execute(db.select(Todo).filter_by(id=id)).scalar_one()
updated_todo.check = request.json["check"]
db.sessionmit()
return "", 204
I'm coding a simple todo list app in Flask for study. My todo model has title, description and a check attribute. When false is a "to do" task, and when the user click on a checkbox it will change to "true", so that task was done. That said, my current PATCH route can handle the title, description and check change, all in one.
So now I was thinking: in my frontend, I'll create the checkbox and when it's clicked the client will send a PATCH request with just the check value; for description and title, I'll create a "edit", so the user can edit those two and when its done he can click in a "save" button, when its clicked the client will send a PATCH request with title and/or description changes.
I realized that there's no way to a request with changes on all the three (title, description and check) could be made, check will be always working alone.
This is my PATCH code:
@app.route("/todo/update/<id>", methods=["PATCH"])
def update_todo(id):
updated_todo = db.session.execute(db.select(Todo).filter_by(id=id)).scalar_one()
if "check" in request.json:
updated_todo.check = request.json["check"]
if "title" in request.json:
updated_todo.title = request.json["title"]
if "description" in request.json:
updated_todo.description = request.json["description"]
db.sessionmit()
return "", 204
Since I'm using if to know what's changing, could I create a new PATCH route just for check and let it work alone? Since I don't need to verify if check is in a title/description PATCH request (it never will be anyway), it'll be a little faster in theory, right? Is there any conceptual or convention problem around it?
It would be something like this:
@app.route("/todo/update/<id>", methods=["PATCH"])
def update_todo(id):
updated_todo = db.session.execute(db.select(Todo).filter_by(id=id)).scalar_one()
if "title" in request.json:
updated_todo.title = request.json["title"]
if "description" in request.json:
updated_todo.description = request.json["description"]
db.sessionmit()
return "", 204
@app.route("/todo/update/check/<id>", methods=["PATCH"])
def update_todo(id):
updated_todo = db.session.execute(db.select(Todo).filter_by(id=id)).scalar_one()
updated_todo.check = request.json["check"]
db.sessionmit()
return "", 204
Share
Improve this question
edited Mar 14 at 21:54
jonrsharpe
122k30 gold badges268 silver badges476 bronze badges
asked Mar 14 at 21:47
Isaac AlfredoIsaac Alfredo
1
1 Answer
Reset to default 0Is there any conceptual or convention problem around it?
Yes; specifically, you seem to be confused about the meaning of "target resource"
PATCH /todo/update/check/1
What this request means is: apply the patch-document enclosed in this request to the /todo/update/check/1
resource. And given your description, that doesn't seem to be what you want the method to do.
The target URI of a PATCH
request, like that of a PUT
request or a DELETE
request, should be the same URI that you use to GET
the representation of the resource.
A typical remote authoring flow would look like
GET /example
# make local changes to the data returned
# create a patch document describing those changes
PATCH /example
Now, your resource model can be anything you want, and edits to the server's copy of a resource can also modify other resource (though you may not always be able to communicate that).
So you could be trying to do something like
GET /todo/1
# Follow the "edit the check" link
GET /todo/update/check/1
# Make your local changes to that
# Create your patch document
PATCH /todo/update/check/1
With a response like
200 OK
Content-Location: /todo/1
# Updated todo representation goes here
"The rules" as it were, might make more sense if you were to see what the standards have to say about cache-invalidation
Also, I see sometimes urls with a /create in the end in POST routes, is it wrong too, right? (like "/todo/create")
You can use any spelling conventions you like for your resource identifiers; that's part of the point. For example, this URL "just works"
https://www.merriam-webster/dictionary/create
How do you tell the web server you want to read a copy of this page?
GET /dictionary/create
How do you tell the web server to replace it's copy of the page with the request body?
PUT /dictionary/create
How do you tell the web server to update it's copy of the page using the patch document attached to the request?
PATCH /dictionary/create
How do you tell the web server to stop serving this web page?
DELETE /dictionary/create
If you design your interactions this way, then all general purpose web components will understand what's going on, and will be able to do useful things (in particular, a cache that has already stored the successful response of a GET request will know to get rid of it when it sees that PUT/PATCH/DELETE was successful).