Skip to content

Commit

Permalink
fix(http_method_override.py): add allowed_methods and bodyless_method…
Browse files Browse the repository at this point in the history
…s attributes to improve readability and maintainability

feat(http_method_override.py): add support for overriding HTTP method using _method form parameter
feat(messages_controller.py): retrieve and pass message object to show method to display message details
feat(messages_controller.py): delete message from database in delete method
feat(messages_controller.py): retrieve and pass message object to edit template to pre-fill form
feat(messages_controller.py): update message in database with form data in update method
feat(messages_controller.py): delete message from database in delete method
feat(messages/edit.html): change _method hidden input value to lowercase "put" to match HTTP method override middleware
feat(messages/show.html): change _method hidden input value to lowercase "delete" to match HTTP method override middleware
feat(request_test.py): add tags to test cases for better organization and filtering
  • Loading branch information
marcuxyz committed Nov 9, 2023
1 parent 8f3b4ce commit 1e69e4a
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 9 deletions.
19 changes: 17 additions & 2 deletions mvc_flask/middleware/http_method_override.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,34 @@


class HTTPMethodOverrideMiddleware:
allowed_methods = frozenset(
[
"GET",
"POST",
"DELETE",
"PUT",
"PATCH",
]
)
bodyless_methods = frozenset(["GET", "HEAD", "OPTIONS", "DELETE"])

def __init__(self, app, input_name="_method"):
self.app = app
self.input_name = input_name

def __call__(self, environ, start_response):
if environ["REQUEST_METHOD"].upper() == "POST":
stream, form, files = parse_form_data(environ)
method = (form.get(self.input_name) or "").upper()

method = form.get(self.input_name)
if method:
if method in self.allowed_methods:
environ["wsgi._post_form"] = form
environ["wsgi._post_files"] = files
environ["REQUEST_METHOD"] = method

if method in self.bodyless_methods:
environ["CONTENT_LENGTH"] = "0"

return self.app(environ, start_response)


Expand Down
8 changes: 7 additions & 1 deletion tests/app/controllers/messages_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ def index(self):
return render_template("messages/index.html", message=message)

def show(self, id):
return render_template("messages/show.html")
message = Message.query.first()

return render_template("messages/show.html", message=message)

def new(self):
return {}, 200
Expand All @@ -34,4 +36,8 @@ def update(self, id):
return redirect(url_for(".index"))

def delete(self, id):
message = Message.query.get(id)
db.session.delete(message)
db.session.commit()

return redirect(url_for(".index"))
3 changes: 2 additions & 1 deletion tests/app/views/messages/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
{% block content %}

<form action="{{ url_for('messages.update', id=1) }}" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="_method" value="put">

<input type="text" name="title" id="title">

<input type="submit" value="send">
Expand Down
6 changes: 4 additions & 2 deletions tests/app/views/messages/show.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

{% block content %}

<form action="{{ url_for('messages.delete', id=1) }}" method="delete">
<form action="{{ url_for('messages.delete', id=1) }}" method="post">
<input type="hidden" name="_method" value="delete">

<input type="submit" value="delete">
</form>

{% endblock content %}
{% endblock content %}
29 changes: 26 additions & 3 deletions tests/request_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ def _(client=client):
assert resp.status_code == 200


@test("should return status 201 for POST (CREATE)", tags=["request"])
@test(
"should return status 201 for POST (CREATE)",
tags=["request", "create", "user", "posts"],
)
def _(client=client, resource=each("user", "posts")):
message = Message(title="Message One")
db.session.add(message)
Expand All @@ -40,7 +43,10 @@ def _(client=client, resource=each("user", "posts")):
assert resp.status_code == 201


@test("request create a messages with json", tags=["create"])
@test(
"should create a message sending json",
tags=["request", "messages", "create", "json"],
)
def _(client=client):
message = Message(title="Message One")
db.session.add(message)
Expand All @@ -57,7 +63,9 @@ def _(client=client):
assert res.json["title"] == "hello, andrews"


@test("must update data from form", tags=["request"])
@test(
"should update message from form", tags=["request", "messages", "update"]
)
def _(browser=browser):
message = Message(title="Message One")
db.session.add(message)
Expand All @@ -69,3 +77,18 @@ def _(browser=browser):

assert browser.url == "/messages"
assert browser.is_text_present("Message updated")


@test(
"should delete message from form", tags=["request", "messages", "delete"]
)
def _(browser=browser):
message = Message(title="Message One")
db.session.add(message)
db.session.commit()

browser.visit(url_for("messages.show", id=message.id))
browser.find_by_value("delete").click()

assert browser.url == "/messages"
assert browser.is_text_not_present("Message updated")

0 comments on commit 1e69e4a

Please sign in to comment.