Django – 更新数据



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

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

我们将使用以下所示的Dreamreal 模型进行练习:

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)

假设您已经完成了迁移并向模型中添加了一些对象。

从 Shell 更新对象

Django 有一个有用的功能,您可以使用它在 Django 项目的环境中调用 Python shell。使用带有manage.py脚本的 shell 命令:

python manage.py shell

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

>>> from myapp.models import Dreamreal

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

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

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

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

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

让我们更新主键为“pk = 2”的对象的名称:

obj.update(name='example')

模型管理器也具有一个get() 方法,它可以获取与给定关键字参数对应的单个实例:

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

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

obj.phonenumber = 24642367570

要使更改持久化,您需要调用save() 方法

obj.save()

通过调用视图函数执行更新操作

现在让我们通过调用视图函数来执行更新操作。在views.py文件中定义update()函数。此函数从其映射的 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文件中注册此视图:

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 https://127.0.0.1:8000/myapp/update/2。浏览器将发出更新成功的消息。

与其像上面示例中那样使用硬编码值,不如希望从用户那里接受数据。我们需要使用与主键对应的对象数据填充 HTML 表单。

修改 update() 视图函数

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

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)

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

修改myform.html脚本如下:

<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 https://127.0.0.1:8000/myapp/update/2 将呈现一个预填充了属于 pk=2 的数据的 HTML 表单。用户可以更新 name 和 phonenumber 字段。

使用 ModelForm 进行更新

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

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'})

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

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

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

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)

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

Django Update Data

UpdateView 类

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

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

views.py文件中添加以下代码:

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()方法。

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 脚本。

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

广告