Python + Django4 to build a personal blog (12): implement the page with the function of deleting articles

In the previous article, we implemented the functions of displaying articles and creating articles respectively.

Python + Django4 to build a personal blog (11): Use forms to realize the functional page of creating articles_Li Weiwei wiwi's blog-CSDN blog In this article, we learned to use the Form class of Django for processing forms, using the inheritance of the forms.ModelForm class Function, we realize the direct correlation between the form and the model. Based on the form function, we completed the functional page for creating articles. In the next two articles, we will gradually complete the functional pages for modifying and deleting the remaining articles. ... https://blog.csdn.net/agelee/article/details/126644558

In this article we implement the function of deleting articles.

Simple function implementation

Deleting articles is very simple in terms of function implementation. The view function is as follows:

# 删文章
def article_delete(request, id):
    # 根据 id 获取需要删除的文章
    article = Article.objects.get(id=id)
    # 调用.delete()方法删除文章
    article.delete()
    # 完成删除后返回文章列表
    return redirect("list")
  • Similar to querying articles, because you need to know which article should be deleted, you must pass in the id of the article;
  • Then call the .delete() function to delete the entry of this article in the database;
  • Return to the article list after successful deletion.

Then modify the routing configuration document

urlpatterns = [
    path('admin/', admin.site.urls),
    path('hello/', views.hello),
    re_path(r'^$', views.article_list),
    path('list/', views.article_list, name='list'),  # 展示文章
    path('detail/<int:id>/', views.article_detail, name='detail'),  # 文章详情
    path('create/', views.article_create, name='create'),  # 写文章
    # 增加生删除文章
    path('delete/<int:id>/', views.article_delete, name='delete'),
]

Finally, modify the template and detail.htmladd a button to delete articles on the details page.

<!-- 文章详情 -->
    <div class="container">
        <!--    <div class="row">-->
        <!-- 标题及作者 -->
        <h1 class="col-12 mt-4 mb-4">{
   
   { article.title }}</h1>
        <div class="col-12 alert alert-primary">
            <div class="col-12">
                <a>作者:{
   
   { article.author }}</a>
                &nbsp
                <a>{
   
   { article.created|date:'Y-m-d H:i:s' }}</a>
                &nbsp
                <a href="{% url "delete" article.id %}">删除文章</a>   #增加此项
            </div>
        </div>
        <!-- 文章正文 -->
        <div class="col-12">
            <p>{
   
   { article.body }}</p>
        </div>
    </div>

After running the server, you can see that a delete article button has been added.

Remove pop-up confirmation function

The above implements a simple function, but there is a hidden danger, that is, if you accidentally click the delete button, you may not even have the chance to regret it.

Generally, for actions involving direct data clearing, a pop-up window confirmation action is required, and the database data can be directly deleted only after a second confirmation.

To achieve this function we can use Bootstrap's modal component.

A modal is a subform that overlays a parent form. Typically, the purpose is to display content from a separate source that can have some interaction without leaving the parent form. Subforms can provide information interaction, etc.

Delete the article code in detail.htmlthe newly added line before and make the following modifications:

 <a href="#" data-bs-toggle="modal" data-bs-target="#myModal">删除文章</a>

A modal box effect has been added. Clicking this link will pop up myModala modal box named.

Then we implement myModalthe function of deleting articles in the modal box.

<!-- 模态框 -->
    <div class="modal fade" id="myModal">
        <div class="modal-dialog modal-dialog-centered modal-sm">
            <div class="modal-content">
                <!-- 模态框头部 -->
                <div class="modal-header">
                    <h4 class="modal-title">确认删除</h4>
                    <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                </div>
                <!-- 模态框主体 -->
                <div class="modal-body">
                    确认删除文章?
                </div>
                <!-- 模态框底部 -->
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="button" class="btn btn-primary" data-dismiss="modal" onclick="confirm_delete()">
                        确定
                    </button>
                </div>
            </div>
        </div>
    </div>
    <script>
        // 删除文章的函数
        function confirm_delete() {
            location.href = '{% url "delete" article.id %}'
        }
    </script>

Here we actually implement two functions.

  • A modal box named myModal is implemented, and two buttons are added to the modal box: Cancel and Confirm. Clicking Confirm will call the JS function confirm_delete()to delete the article.
  • I wrote a function confirm_delete()that will call Django's delete article url:deleteto implement the deletion function.

safe way

You may think that the function of deleting articles is not difficult to implement, but please note that the above method has hidden dangers . To continue the discussion in depth, we have to mention cross-site request forgery attacks , also known as CSRF attacks (Cross-site request forgery).

CSRF attack

You can understand a CSRF attack as: the attacker steals your identity and sends malicious requests in your name. Let’s take deleting articles as an example:

  • The user logged into blog website A , and the browser recorded the session and maintained the logged-in status;
  • The user accidentally opened the evil attack website B without logging out ;
  • Attacking website B implants malicious code into the page and silently sends a request to delete the article to blog website A. At this time, the browser mistakenly thinks that the user is operating, and successfully performs the deletion operation.

Due to the browser's same-origin policy, a CSRF attacker cannot obtain the actual content of your login data, but can trick the browser into attaching the correct login data to the malicious request. Don’t underestimate the power of CSRF attacks: if your bank account has such security holes, hackers can transfer all your deposits without anyone noticing.

So how to prevent the risk of CSRF attacks here? There is a method, that is, use the POST method when deleting an article, and verify the csrf token.

CSRF token

We mentioned earlier that csrf_token must be added when submitting a form in Django. This is the CSRF token. The process of preventing CSRF attacks is as follows:

  • When a user visits a Django site, there is an implicit field csrf_token in the form fed back to the user by Django. This value is randomly generated on the server side and is different every time;
  • Before the backend processes the POST request, Django will verify whether the csrf_token in the requested cookie is consistent with the csrf_token in the form. If they are consistent, the request is legitimate. Otherwise, the request may come from a CSRF attack and 403 Server Forbidden Access will be returned.

Since the attacker cannot obtain the user's cookie content (just relies on the browser to forward it), it is usually impossible to construct the correct csrf_token, thus preventing such attacks.

Use Form to send Post request

To send a Post request in Django, you can specify the request method in the Form.

First, add a hidden Form below the delete article button code:

 <a href="#" data-bs-toggle="modal" data-bs-target="#myModal">删除文章</a>
                <!-- 新增一个隐藏的表单 -->
                <form
                        style="display:none;"
                        id="safe_delete"
                        action="{% url "delete" article.id %}"
                        method="POST"
                >
                    {% csrf_token %}
                    <button type="submit">发送</button>
                </form>

Next we modify our confirm_delete()function.

 <script>
        // 删除文章的函数
        function confirm_delete() {
            document.getElementById("safe_delete").submit();
        }
    </script>

Finally, we transform the view function:

# 删文章
def article_delete(request, id):
    print(request.method)
    if request.method == 'POST':
        # 根据 id 获取需要删除的文章
        article = Article.objects.get(id=id)
        # 调用.delete()方法删除文章
        article.delete()
        return redirect("list")
    else:
        return HttpResponse("仅允许post请求")

Previously, our function was to directly call the URL to request Django's view deletion function.

Now after our transformation, the code process for deleting articles is as follows:

  • When clicking the delete article link, a modal box pops up
  • After clicking the confirmation button of the modal box, find the hidden Form through the JS function code and submit the form.
  • The form initiates a POST request and carries the csrf token (Django verifies all POST requests through middleware by default csrf ), thus avoiding csrf attacks.

Conclusion

In this article, we learned how to implement the function of deleting articles, and also used Bootstrap's modal pop-up box to perform secondary verification of deleted articles.

When it comes to the deletion function, in order to increase data security, we briefly introduced Django's csrf token protection mechanism, and enabled Django's crsfverification mechanism by using a hidden form and sending a Post request.

The deletion function actually has an important verification: user verification, which we have not covered yet. We will arrange to add it later when adding user module functions.

In the next article, you will learn how to update an article.

Guess you like

Origin blog.csdn.net/agelee/article/details/126702871
Recommended