You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
92
100
93
101
Time to create a URL (in `blog/urls.py`):
94
102
@@ -101,10 +109,13 @@ and finally, a *view* (as always, in `blog/views.py`):
101
109
```python
102
110
defpost_publish(request, pk):
103
111
post = get_object_or_404(Post, pk=pk)
104
-
post.publish()
112
+
if request.method=='POST':
113
+
post.publish()
105
114
return redirect('post_detail', pk=pk)
106
115
```
107
116
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
+
108
119
Remember, when we created a `Post` model we wrote a method `publish`. It looked like this:
109
120
110
121
```python
@@ -123,10 +134,14 @@ Congratulations! You are almost there. The last step is adding a delete button!
123
134
124
135
## Delete post
125
136
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:
0 commit comments