Django 更新数据
Django ORM 使用 Active Record 模式来处理 model class 与其映射的数据库表之间的交互。model class 的一个实例对应表中的一行数据。对象的任何属性更改都会更新对应的行。
在本章中,我们将重点介绍 Django 中更新关系数据库中已有行的不同方法。
我们将使用以下 Dreamreal model 进行练习 −
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)
假设您已经执行了 migrations 并在 model 中添加了一些对象。
从 Shell 更新对象
Django 提供了一个有用的功能,可以在 Django 项目环境中调用 Python shell。使用 manage.py 脚本运行 shell 命令 −
python manage.py shell
在 Python 提示符前,导入 Dreamreal model −
>>> from myapp.models import Dreamreal
model.objects 属性返回 model Manager,其 all() 方法返回一个 QuerySet。我们可以通过应用 filter 来限制集合中的对象。
要返回 primary key 为 2 的对象,使用以下语句 −
obj = Dreamreal.objects.filter(pk = 2)
model class 具有 get() 实例方法,可以用来更改一个或多个属性的值。
obj.update(f1=v1, f2=v2, . . .)
让我们更新 "pk = 2" 的对象的 name −
obj.update(name='example')
model manager 还具有 get() 方法,它根据给定的关键字参数获取单个实例 −
obj = Dreamreal.objects.get(phonenumber = 2376970)
我们可以使用简单的赋值来更新属性。让我们更改电话号码 −
obj.phonenumber = 24642367570
要使更改持久化,需要调用 save() 方法 −
obj.save()
通过调用 View Function 执行更新操作
现在让我们通过调用 view function 来执行更新操作。在 views.py 文件中定义 update() 函数。该函数从其映射的 URL 接收 primary key 作为参数。
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 文件中注册这个 view,通过添加一个新 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。浏览器将显示更新成功的消息。
与上述示例中使用硬编码值不同,我们希望从用户那里接受数据。我们需要使用 primary key 对应的对象数据填充 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 http://localhost:8000/myapp/update/2 会渲染一个预填充了 pk=2 数据的 HTML 表单。用户可以更新 name 和 phonenumber 字段。
使用 ModelForm 进行更新
接下来,我们将使用 ModelForm class 来渲染 HTML 表单,其输入元素对应模型字段类型。使用继承 ModelForm 的 DreamrealForm class。
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 字段的 readonly 属性。
视图函数 update() 像之前一样从 URL 中接收 primary key 参数。当使用 POST 方法调用此函数时,表单数据用于更新现有对象。
当使用 GET 方法时,Django 获取对应 primary key 的对象,并使用其属性填充 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)
访问 http://localhost:8000/myapp/update/1 URL 以显示填充了 pk=1 记录的 HTML 表单。您可以更改值并提交以更新对应的对象。
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 脚本,因为它会根据相应的 model 渲染 HTML 脚本。
访问 updateview/1 URL,以渲染预填充了主键为 1 的对象表单。尝试更改一个或多个值并更新表格。