Skip to content

Commit 899ab34

Browse files
authored
Merge pull request #178 from shaib/feat/publish-delete-as-post
"add more to your website": Made "Publish"/"Delete" use POST
2 parents a2bff42 + e573fa9 commit 899ab34

1 file changed

Lines changed: 22 additions & 6 deletions

File tree

en/homework/README.md

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,19 @@ into these:
8484
{{ post.published_date }}
8585
</div>
8686
{% else %}
87-
<a class="btn btn-default" href="{% url 'post_publish' pk=post.pk %}">Publish</a>
87+
<form method="POST" action="{% url post_publish pk=post.pk %} class="post-form">{% csrf_token %}
88+
<button type="submit" class="post btn btn-info" name="publish">Publish</button>
89+
</form>
8890
{% endif %}
8991
```
9092

91-
As you noticed, we added {% raw %}`{% else %}`{% endraw %} line here. That means, that if the condition from {% raw %}`{% if post.published_date %}`{% endraw %} is not fulfilled (so if there is no `published_date`), then we want to do the line {% raw %}`<a class="btn btn-default" href="{% url 'post_publish' pk=post.pk %}">Publish</a>`{% endraw %}. Note that we are passing a `pk` variable in the {% raw %}`{% url %}`{% endraw %}.
93+
As you noticed, we added {% raw %}`{% else %}`{% endraw %} line here. That means, that if the condition from {% raw %}`{% if post.published_date %}`{% endraw %} is not fulfilled (so if there is no `published_date`), then we want to do the lines with `<form ... </form>`. But wait -- why are we bothering with a form here? There are no fields to fill in. Why are we not creating the publish button using an `<a class="btn">` element like we did before?
94+
95+
So far, we have glossed over the difference between user actions which only retrieve data to show (like listing the posts), on one hand, and actions which change the data (like creating a new post) on the other hand. It is useful for all kinds of software running on the web (including your web browser) to be able to tell the difference between the two, before sending the relevant requests. To facilitate this, the web standards define GET requests as retrieval-only operations, and POST requests as potentially-data-changing operations.
96+
97+
As you may have noticed, when a user clicks an `<a>` element, the browser sends out a GET request. So these elements are not suitable for data-changing operations. Since publishing the blog-post changes the data on the server, an `<a>` element is not suitable here. In order to generate a POST request, we need to create a form.
98+
99+
Now, let's take a look at the details of the form. We are using a new attribute, `action`, to specify that the form is submitted to a URL that is different from the one on which it is presented. As before, we are using a {% raw %}`{% url %}`{% endraw %} template-tag, and are passing a `pk` variable to it. The rest is as it was with the edit form -- the {% raw %}`{% csrf_token %}`{% endraw %} for security, and the submit button.
92100

93101
Time to create a URL (in `blog/urls.py`):
94102

@@ -101,10 +109,13 @@ and finally, a *view* (as always, in `blog/views.py`):
101109
```python
102110
def post_publish(request, pk):
103111
post = get_object_or_404(Post, pk=pk)
104-
post.publish()
112+
if request.method=='POST':
113+
post.publish()
105114
return redirect('post_detail', pk=pk)
106115
```
107116

117+
Note that we check the request method before executing the operation -- although the pages we will emit will not include a direct link to the URL of this view, and so one could think this check is redundant, in practice this sort of "defensive programming" often pays off, preventing damage which could have been caused by bugs.
118+
108119
Remember, when we created a `Post` model we wrote a method `publish`. It looked like this:
109120

110121
```python
@@ -123,10 +134,14 @@ Congratulations! You are almost there. The last step is adding a delete button!
123134

124135
## Delete post
125136

126-
Let's open `blog/templates/blog/post_detail.html` once again and add this line:
137+
Let's open `blog/templates/blog/post_detail.html` once again and add these lines:
127138

128139
```django
129-
<a class="btn btn-default" href="{% url 'post_remove' pk=post.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
140+
<form method="POST" action="{% url post_remove pk=post.pk %} class="post-form">{% csrf_token %}
141+
<button type="submit" class="post btn btn-danger" name="delete">
142+
<span class="glyphicon glyphicon-remove"></span>
143+
</button>
144+
</form>
130145
```
131146

132147
just under a line with the edit button.
@@ -142,7 +157,8 @@ Now, time for a view! Open `blog/views.py` and add this code:
142157
```python
143158
def post_remove(request, pk):
144159
post = get_object_or_404(Post, pk=pk)
145-
post.delete()
160+
if request.method=='POST':
161+
post.delete()
146162
return redirect('post_list')
147163
```
148164

0 commit comments

Comments
 (0)