Skip to content

Commit

Permalink
Merge pull request #178 from shaib/feat/publish-delete-as-post
Browse files Browse the repository at this point in the history
"add more to your website": Made "Publish"/"Delete" use POST
  • Loading branch information
amakarudze authored Jun 8, 2024
2 parents a2bff42 + e573fa9 commit 899ab34
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions en/homework/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,19 @@ into these:
{{ post.published_date }}
</div>
{% else %}
<a class="btn btn-default" href="{% url 'post_publish' pk=post.pk %}">Publish</a>
<form method="POST" action="{% url post_publish pk=post.pk %} class="post-form">{% csrf_token %}
<button type="submit" class="post btn btn-info" name="publish">Publish</button>
</form>
{% endif %}
```

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 %}.
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?

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.

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.

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.

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

Expand All @@ -101,10 +109,13 @@ and finally, a *view* (as always, in `blog/views.py`):
```python
def post_publish(request, pk):
post = get_object_or_404(Post, pk=pk)
post.publish()
if request.method=='POST':
post.publish()
return redirect('post_detail', pk=pk)
```

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.

Remember, when we created a `Post` model we wrote a method `publish`. It looked like this:

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

## Delete post

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

```django
<a class="btn btn-default" href="{% url 'post_remove' pk=post.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
<form method="POST" action="{% url post_remove pk=post.pk %} class="post-form">{% csrf_token %}
<button type="submit" class="post btn btn-danger" name="delete">
<span class="glyphicon glyphicon-remove"></span>
</button>
</form>
```

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

Expand Down

0 comments on commit 899ab34

Please sign in to comment.