首页  >  文章  >  后端开发  >  Python 和 Django 中的 CRUD 操作 - 第 2 部分

Python 和 Django 中的 CRUD 操作 - 第 2 部分

王林
王林原创
2024-07-25 15:17:12948浏览

在上一篇文章中,我们介绍了设置 Django 项目的基础知识并创建了练习模型,我们将其以列表的形式显示在前端。在本文中,我们将深入探讨执行 CRUD 操作。对于那些不熟悉的人来说,CRUD 代表创建、读取、更新和删除 — 本质上是您可以对数据执行的四个基本操作。

现在我们已经在应用文件夹中设置了 API,我们只需扩展索引视图即可处理创建、更新和删除请求。

表格

让我们设置一个允许用户创建练习的表单。我们将再次使用 HTML 模板来实现此目的。首先,在 app/templates 文件夹中创建一个名为 add_exercise.html 的新模板。

<form method="POST" action="/">
    {% csrf_token %}
    <input type="text" name="title" placeholder="Enter the title" />
    <input type="date" name="date"  placeholder="Enter the date" />
    <button type="submit">Save</button>
</form>

接下来,在我们的 index.html 模板中,我们将使用以下方法包含 add_exercise.html 模板:

{% extends "base.html" %} {% block content %}
    <h2>Exercises</h2>
    {% include 'add_exercise.html' %}
...
{% endblock %}

我们在这里使用 include 标签,它可以提高 HTML 模板的可组合性,使我们的代码更易于维护和理解。如果您在浏览器中刷新页面,您应该会看到表单出现在屏幕上。

Add Exercise

在我们的 HTML 中,我们使用

 方法属性设置为 POST 且操作属性指向 / 的标记,这与我们用来获取练习列表的端点相同。

在这种情况下,csrf_token 是由随机生成的秘密值表示的安全功能。它有助于保护我们提交的表单免受伪造攻击,这就是 CSRF 的意思——跨站请求伪造。为每个用户会话生成一个唯一的令牌,第三方站点无法访问该令牌,从而防止发生未经授权的更改。

我们的表单包含两个输入字段:一个用于标题,另一个用于日期,遵循我们的练习模型的架构。提交表单后,标题和日期的值将通过 POST 请求发送到 / 端点,然后由 app/views.py 中的索引视图进行处理。

模型

在 Django 中,我们可以通过添加与 CRUD 操作相对应的特定方法来增强我们的 Exercise 模型(本质上是一个 Python 类)。在 app/models.py 文件中,我们将包含以下内容:

class Exercise(models.Model):
    ...

    def create(request):
        title = request.POST.get('title')
        date = request.POST.get('date')

        exercise = Exercise.objects.create(title=title, date=date)

        return exercise

我们可以从 POST 请求访问标题和日期,如上面的代码所示。然后,我们可以利用 Django 内置的 ORM 创建一个新的练习并返回创建的实例。

我们将利用用于检索练习的相同索引视图,扩展它以检查请求方法是否为 POST。如果是这样,我们将把请求对象传递给我们之前定义的类方法。创建练习后,我们会将用户重定向回主页或执行页面刷新,确保新添加的练习出现在屏幕上。

from django.http import HttpResponseRedirect

from app import models

...

def index(request):
    if request.method == 'POST':
        models.Exercise.create(request)
        return redirect('/')

    exercises = (
        models.Exercise.objects.all().order_by("created_at")
    )
    return render(request, "index.html", context={'exercises': exercises})

现在尝试创建一个新练习,您应该会看到它出现在列表底部。

更新练习

在向练习中添加更新功能之前,让我们先重构一下代码。我们将把练习移至他们自己的模板,名为 exercise.html。

<h2>Exercises</h2>
{% include 'add_exercise.html' %}
<ul style="margin: 0; list-style: none; padding: 0">
    {% for exercise in exercises %}
        <li style="margin-top: 4px">
            {% include 'exercise.html' %}
        </li>
    {% endfor %}
</ul>

在 app/templates 文件夹中为 exercise.html 创建一个模板,我们将向其中添加以下 HTML:

<form method="POST" action="/">
    {% csrf_token %}
    <input hidden name="id" value="{{exercise.id}}" />
    <input
        type="text"
        name="title"
        value="{{exercise.title}}"
        placeholder="Enter the title"
    />
    <input
        type="date"
        name="date"
        placeholder="Enter the date"
        value="{{exercise.date | date:'Y-m-d'}}"
    />
    <button type="submit" name="update">Update</button>
</form>

我们使用

 再次标记列表中的每个练习,并为 exercise.id 添加隐藏输入,该输入将用于更新练习。返回浏览器并刷新页面;您应该会看到列表中每个练习的表格,每个输入都预先填充了相应的练习数据。

CRUD Operations In Python & Django - Part 2

请注意,我们没有使用 PUT 作为表单方法;相反,我们使用 POST。这是因为视图处理程序只能解析通过 GET 和 POST 请求发送的数据,没有对 PUT 和 DELETE 的内置支持。当我们在 Exercise 类中创建 create 类方法时,您可能已经注意到我们使用了 request.POST.get('title')。虽然这适用于 POST 请求,但请求对象中没有可用的 PUT 或 DELETE 方法。

但是我们如何区分 POST 和 PUT 请求呢?如果您检查我们之前创建的表单,您会注意到我们为提交按钮分配了一个名称属性。我们可以使用 request.POST.get('update') 以与访问标题和日期相同的方式访问此属性。

让我们更新创建练习表单以包含相同的更改。

<form method="POST" action="/">
    ...
    <button type="submit" name="create">Save</button>
</form>

在我们的练习视图中,我们将进行以下更改以区分不同的请求。

def index(request):
    if request.method == 'POST':
        create = 'create' in request.POST
        update = 'update' in request.POST

        if create == True:
            models.Exercise.create(request)
        elif update == True:
            models.Exercise.update(request)

        return redirect('/')

    exercises = (
        models.Exercise.objects.all().order_by("created_at")
    )
    return render(request, "index.html", context={'exercises': exercises})

We check for the button name and forward the request to the appropriate Exercise method accordingly.

Let's add an update class method to the Exercise model in app/models.py.

def update(request):
    id = request.POST.get('id')
    title = request.POST.get('title')
    date = request.POST.get('date')

    exercise = Exercise.objects.filter(pk=id).update(title=title, date=date)

    return exercise

To update a row in the database, we can use the update method available on the Exercise model. However, before updating, we need to ensure that we are updating the correct exercise. To do this, we filter the exercises by the primary key, which is id, and update only that specific exercise.

Delete Exercise

Similarly, we’ll add a delete button next to each exercise in the exercise.html template.

<form method="POST" action="/">
    ...
    <button type="submit" name="update">Update</button>
    <button type="submit" name="delete">Delete</button>
</form>

We’ll set delete as the value of the name attribute, and in views.py, we’ll extend the if...elif statements to handle the delete operation.

def index(request):
    if request.method == 'POST':
        create = 'create' in request.POST
        update = 'update' in request.POST
        delete = 'delete' in request.POST

        if create == True:
            models.Exercise.create(request)
        elif update == True:
            models.Exercise.update(request)
        elif delete == True:
            models.Exercise.delete(request)

        return redirect('/')

    exercises = (
        models.Exercise.objects.all().order_by("created_at")
    )
    return render(request, "index.html", context={'exercises': exercises})

And in the Exercise model, we'll add the class method delete.

def delete(request):
    id = request.POST.get('id')
    is_deleted = Exercise.objects.filter(pk=id).delete()

    if is_deleted == 1:
        return True

    return False

With this addition, we've successfully implemented CRUD operations in our Python and Django application.

Key Takeaways

  1. Django view handlers do not support PUT and DELETE requests, as they do not parse the query parameters or request body for those HTTP methods. As a result, we must rely on POST requests and differentiate between them by passing an additional field in the request body.
  2. Noticed that I'm making the POST request to the same route from which I'm fetching the exercises. This is important because if you were to create an endpoint like /api/exercises to handle requests, you would need to manage redirection manually. Otherwise, the behavior of the tag after the request is to redirect the user to the endpoint specified in the action attribute. Therefore, you will need to manually redirect the user back to the desired page, or in our case, keep the user on the same page.
from django.http import HttpResponseRedirect

def index(request):
    ...

    return redirect('/')
    # or
    return HttpResponseRedirect(request.META['HTTP_REFERER'])

In summary, by effectively managing our POST requests and ensuring proper redirection, we can create a seamless user experience while implementing CRUD operations in our Django application.

以上是Python 和 Django 中的 CRUD 操作 - 第 2 部分的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn