Django 简明教程

Django – Update Data

Django ORM 使用活动记录模式进行模型类及其映射的数据库表之间的交互。模型类的实例对应于表中的一行。对象的任何属性都会导致更新相应行。

Django ORM uses the Active Record pattern for the interaction between a model class and its mapped database table. An instance of the model class corresponds to a single row in the table. Any of the attributes of the object results in updating the corresponding row.

在本章中,我们将重点介绍 Django 中可用的不同方式,以更新关系数据库中已存在的行。

In this chapter, we will focus on the different ways available in Django to update an already existing row in a relational database.

我们将使用下面给出的 Dreamreal model 作为本次练习:

We shall use the Dreamreal model as given below for the exercise −

class Dreamreal(models.Model):
   website = models.CharField(max_length=50)
   mail = models.CharField(max_length=50)
   name = models.CharField(max_length=50)
   phonenumber = models.IntegerField()

   def __str__(self):
      return "Website: {} Email: {} Name: {} Ph.: {}".format(self.website, self.mail, self.name, self.phonenumber)

假设您已经执行了迁移,并在模型中添加了一些对象。

It is assumed that you have already performed the migrations and added a few objects in the model.

Update Object From Shell

Django 具有一个有用的功能,可以使用此功能在 Django 项目的环境中调用 Python shell。使用命令 manage.py 与脚本一起使用 shell 命令 -

Django has a useful feature with which you can invoke a Python shell inside the Django project’s environment. Use the shell command with the manage.py script −

python manage.py shell

在 Python 提示符前,导入 Dreamreal 模型 -

In front of the Python prompt, import the Dreamreal model −

>>> from myapp.models import Dreamreal

model.objects 属性返回模型管理器,其 all() 方法返回 QuerySet。我们可以通过应用过滤器来限制集合中的对象。

The model.objects attribute returns the model Manager, and its all() method returns a QuerySet. We can limit the objects in the set by applying the filter.

要返回主键为 2 的对象,请使用以下语句 -

To return the object with its primary key as 2, use the following statement −

obj = Dreamreal.objects.filter(pk = 2)

模型类具有 get() 实例方法,我们可使用此方法更改一个或多个属性的值。

The model class has the get() instance method with which we can change the value of one or more attributes.

obj.update(f1=v1, f2=v2, . . .)

让我们将“pk = 2”对象的名称更新为 -

Let us update the name of the object with "pk = 2" −

obj.update(name='example')

模型管理器还具有 get() method ,该管理器获取对应于给定关键字参数的单个实例 -

The model manager also has a get() method that fetches a single instance corresponding to the given keyword argument −

obj = Dreamreal.objects.get(phonenumber = 2376970)

我们可以使用一个简单的赋值来更新一个属性。让我们更改电话号码 -

We can use a simple assignment to update an attribute. Let us change the phone number −

obj.phonenumber = 24642367570

要使更改持久化,您需要调用 save() method -

To make the change persistent, you need to call the save() method

obj.save()

Perform Update Operation by Calling a View Function

现在让我们通过调用视图函数执行更新操作。在 views.py 文件中定义 update() 函数。此函数从其映射的 URL 接收主键作为参数。

Let us now perform the update operation by calling a view function. Define the update() function in views.py file. This function receives the primary key as the argument from its mapped URL.

from django.shortcuts import render
from django.http import HttpResponse
from myapp.models import Dreamreal

def update(request, pk):
   obj = Dreamreal.objects.get(pk=pk)
   obj.name="admin"
   obj.save()
   return HttpResponse("Update successful")

我们还需要通过添加新路径在 urls.py 文件中注册此视图 -

We also need to register this view in the urls.py file by adding a new path −

from django.urls import path
from . import views
from .views import DRCreateView, update

urlpatterns = [
   path("", views.index, name="index"),
   path("addnew/", views.addnew, name='addnew'),
   path("update/<int:pk>", views.update, name='update'),
]

运行 Django 服务器并访问 URL http://localhost:8000/myapp/update/2 。浏览器会发出更新成功消息。

Run the Django server and visit the URL http://localhost:8000/myapp/update/2. The browser emits the update success message.

我们不希望像上述示例中那样使用硬编码值,而是期待用户输入数据。我们需要使用对应于主键的对象数据填充 HTML 表单。

Instead of using the hard-coded values as in the above example, we would like the data to be accepted from the user. We need to populate a HTML form with the object data corresponding to the primary key.

Modify the update() View Function

修改 update() 视图函数,如下所示:

Modify the update() view function as shown −

from django.shortcuts import render
from django.http import HttpResponse
from myapp.models import Dreamreal

def update(request, pk):
   obj = Dreamreal.objects.get(pk=pk)
   if request.method == "POST":
      ws = request.POST['website']
      mail = request.POST['mail']
      nm = request.POST['name']
      ph = request.POST['phonenumber']
      obj.name = nm
      obj.phonenumber = ph
      obj.save()
      return HttpResponse("<h2>Record updated Successfully</h2>")
   obj = Dreamreal.objects.get(pk=pk)
   context = {"obj":obj}
   return render(request, "myform.html", context)

我们需要使用模板变量,用对象属性的值填充表单元素。

We need to populate the form elements with the values of object attributes with the template variables.

修改 myform.html 脚本,如下所示:

Modify the myform.html script as follows −

<html>
<body>
   <form action="../update/{{ obj.pk }}" method="post">
      {% csrf_token %}
      <p><label for="website">WebSite: </label>
      <input id="website" type="text" value = {{ obj.website }} name="website" readonly></p>
      <p><label for="mail">Email: </label>
      <input id="mail" type="text" value = {{ obj.mail }} name="mail" readonly></p>
      <p><label for="name">Name: </label>
      <input id="name" type="text" value = {{ obj.name }} name="name"></p>
      <p><label for="phonenumber">Phone Number: </label>
      <input id="phonenumber" type="text" value = {{ obj.phonenumber }} name="phonenumber"></p>
      <input type="submit" value="Update">
   </form>
</body>
</html>

访问 URL http://localhost:8000/myapp/update/2 将呈现一个 HTML 表单,该表单预先填充了属于 pk=2 的数据。用户可以更新 name 和 phonenumber 字段。

Visiting the URL http://localhost:8000/myapp/update/2 renders a HTML form pre-populated with the data belonging to pk=2. User can update the name and phonenumber fields.

Using ModelForm for Update

接下来,我们将使用 ModelForm 类呈现一个 HTML 表单,其 input 元素对应于模型字段类型。使用继承 Modelform 的 DereamrealForm 类

Next, we shall use the ModelForm class to render a HTML form with its input elements corresponding to the model field types. Let use the DereamrealForm class that inherits the Modelform

from django import forms
from .models import Dreamreal

class DreamrealForm(forms.ModelForm):
   class Meta:
      model = Dreamreal
      fields = "__all__"

      def __init__(self, *args, **kwargs):
         super(DreamrealForm, self).__init__(*args, **kwargs)
         self.fields['website'].widget = forms.TextInput(attrs={'readonly': 'readonly'})
         self.fields['mail'].widget = forms.TextInput(attrs={'readonly': 'readonly'})

Note - 在这里,我们在类构造函数中设置了 website 和 mail 字段的只读属性。

Note − Here, we have set the readonly property of the website and mail fields in the class constructor.

视图函数 update() 从 URL 中接收主键参数,如同之前一样。当该函数使用 POST 方法调用时,表单数据将用于更新现有对象。

The View function update() receives the primary key argument from the URL as before. When this function is called with POST method, the form data is used to update the existing object.

当使用 GET 方法时,Django 会抓取对应于主键的对象,并使用其属性填充 HTML 表单:

When the GET method is used, Django fetches the object corresponding to the primary key, and uses its attributes to populate the HTML form −

def update(request, pk):
   obj = Dreamreal.objects.get(pk=pk)
   if request.method == "POST":
      form = DreamrealForm(request.POST)
      if form.is_valid():
         form.save()
         return HttpResponse("<h2>Record updated Successfully</h2>")
   obj = Dreamreal.objects.get(pk=pk)
   context = {"obj": DreamrealForm(instance=obj), "pk": obj.pk}
   return render(request, "myform.html", context)

访问 http://localhost:8000/myapp/update/1 URL 以显示 HTML 表单,其字段已用 pk=1 的记录填充。您可以更改值,并提交对应的对象以进行更新。

Visit the http://localhost:8000/myapp/update/1 URL to display the HTML form with its fields filled with the record with pk=1. You can change the values and submit for the corresponding object to be updated.

django update data

The UpdateView Class

Django 定义了一组通用视图类。 UpdateView class 专门设计用于执行 INSERT 查询操作。

Django defines a collection of generic view classes. The UpdateView class is specially designed for performing the INSERT query operation.

我们定义 UpdateView 类的子类,并将其 template_name 属性设置为我们已创建的 myform.html

We define a subclass of UpdateView class and set its template_name property to myform.html that we have already created.

将以下代码添加到 views.py 文件中−

Add the following code in views.py file −

from django.views.generic.edit import UpdateView
class DRUpdateView(UpdateView):
   model = Dreamreal
   fields = '__all__'
   template_name = "myform.html"
   success_url = "../success/"

为了注册此视图,我们需要为我们的应用更新 urls.py 文件。请注意,要注册通用视图,我们需要使用 as_view() 方法。

To register this view, we need to update the urls.py file for our app. Note that, to register a generic view, we use the as_view() method.

from django.urls import path
from . import views
from .views import DRCreateView, update, DRUpdateView

urlpatterns = [
   path("", views.index, name="index"),
   path("addnew/", views.addnew, name='addnew'),
   path("add/", DRCreateView.as_view(), name='add'),
   path("success/", views.success, name='success'),
   path("update/<int:pk>", views.update, name='update'),
   path("updateview/<int:pk>", views.update, name='update'),
]

我们不需要更改 myform.html 脚本,因为它将根据各个模型呈现 HTML 脚本。

We need not change the myform.html script, as it renders the HTML script based on the respective model.

访问 updateview/1 URL 以呈现预先填充了主键 = 1 的对象的表单。尝试更改一个或多个值并更新该表。

Visit the updateview/1 URL to render the form pre-filled with the object having primary key = 1. Try and change one or more values and update the table.