记录一次关于表单与模型进行数据交互的自学内容。
1,项目index中的模型文件model.py:
from django.db import models# Create your models here.class PersonInfo(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=20)age = models.IntegerField()def __str__(self):return self.nameclass Meta:verbose_name = \'人员信息\'class Vocation(models.Model):id = models.AutoField(primary_key=True)job = models.CharField(max_length=20)title = models.CharField(max_length=20)payment = models.IntegerField(null=True, blank=True)person = models.ForeignKey(PersonInfo, on_delete=models.Case)def __str__(self):return str(self.id)class Meta:verbose_name = \"职业信息\"
前提说明:
1),使用默认的sqlite数据库。
2),一个模型对应数据库中的一张表,表与表间的三种关联关系分别由OneToOneField、ForeignKey和ManyToManyField表示。在完成数据迁移后,index_personinfo与index_vocation是一对多关系。
3),路由略。
2,向表中添加数据:
3,项目index中的模型文件form.py:
from django import formsfrom index.models import *from django.core.exceptions import ValidationError# 自定义验证def payment_validate(value):if value > 30000:raise ValidationError(\'请输入合理薪资\')class VocationForm(forms.Form):use_required_attribute = Falsejob = forms.CharField(max_length=20, label=\'职位\',required=False)title = forms.CharField(max_length=20,label=\'职称\',widget=forms.widgets.TextInput(attrs={\'class\': \'jobtitle\'}),error_messages={\'required\': \'职称不能为空!\'})payment = forms.IntegerField(label=\'薪资\',widget=forms.widgets.TextInput(attrs={\'class\': \'jobpayment\',\'placeholder\': u\'人民币数值(单位:元)\'}),validators=[payment_validate])# 设置下拉选项value = PersonInfo.objects.values(\'name\')choices = [(i + 1, v[\'name\']) for i, v in enumerate(value)]person = forms.ChoiceField(choices=choices, label=\'姓名\')def clean_title(self):data = self.cleaned_data[\'title\']return \'初级\' + data
说明:字段参数使用了validators,就不再用error_messages了。
4,项目index中的视图文件view.py及模板index.html:
from django.shortcuts import renderfrom django.http import HttpResponse, HttpResponsePermanentRedirect, HttpResponseRedirect, Http404, \\StreamingHttpResponse, FileResponse, JsonResponsefrom .models import PersonInfo, Vocationfrom .form import VocationFormdef index(request):# GET请求if request.method == \'GET\':id = request.GET.get(\'id\', \'\')# GET请求带参数时:http://127.0.0.1:8000/?id=1if id:# 根据请求参数从模型获取数据d = Vocation.objects.filter(id=id).values()d = list(d)[0]print(\"get d:\", d)d[\'person\'] = d[\'person_id\'] # Vocation外键为person_id# VocationForm对应字段为personi = dict(initial=d, label_suffix=\'*\', prefix=\'vv\')# 将参数i传入表单VocationForm执行实例化v = VocationForm(**i)# GET请求不带参数时:http://127.0.0.1:8000else:v = VocationForm(prefix=\'vv\')return render(request, \'index.html\', locals())# POST请求else:v = VocationForm(data=request.POST, prefix=\'vv\')if v.is_valid():# 获取网页控件name的数据# 方法一title = v[\'title\']# 方法二# cleaned_data将控件name的数据进行清洗ctitle = v.cleaned_data[\'title\']# 在http://127.0.0.1:8000/?id=1页面下,将数据更新到模型Vocationid = request.GET.get(\'id\', \'\')d = v.cleaned_datad[\'person_id\'] = int(d[\'person\'])print(\"post d:\", d)# 使用请求参数提交if id:Vocation.objects.filter(id=id).update(**d)msg = \'使用请求参数提交成功\'return HttpResponse(msg)# 直接修改表提交# 在http://127.0.0.1:8000页面下,将数据更新到模型Vocationelse:# 反向查询再修改id = d[\"person\"]query_set = PersonInfo.objects.filter(id=id).first()print(\"query_set\", query_set)result_set = query_set.vocation_set.first()print(\"result_set\", result_set)Vocation.objects.filter(id=id).update(**d)msg = \'直接修改表提交成功\'return HttpResponse(msg)else:# 获取错误信息,并以json格式输出error_msg = v.errors.as_json()print(error_msg)return render(request, \'index.html\', locals())
<!DOCTYPE html><html lang=\"en\"><head><title>title</title></head><body>{% if v.errors %}<p>数据出错,出错信息为:{{ v.errors }}</p>{% else %}<form action=\"\" method=\"post\">{% csrf_token %}<table>{{ v.as_table }}</table><input type=\"submit\" value=\"提交\"></form>{% endif %}</body></html>
从四种情况说明:
1),当django接受不带参数的GET请求:http://127.0.0.1:8000时,实例化表单类:v = VocationForm(prefix=‘vv’),其中prefix参数通过设置表单在html中的name和id,允许在不同网页中使用同一个表单类生成不同表单。如下图:
2),通过请求参数获取并展示数据。
当django接受带参数的GET请求:http://127.0.0.1:8000/?id=1时,根据id参数,使用ORM API,从index_vocation表中查询相关数据: d = Vocation.objects.filter(id=id).values(),给查询结果添加VocationForm外键person数据,才能获得完整的VocationForm初始化数据,其中print(“get d:”, d)输出get d: {‘id’: 1, ‘job’: ‘喊666’, ‘title’: ‘高级程序员鼓励师’, ‘payment’: 9999, ‘person_id’: 1}。初始化时要使用prefix参数进行表单识别。如下图:
3),在情况2的结果页面下,可以修改除姓名以外的任何数据并完成提交。
POST请求将所有数据发送给django,然后django实例化表单类,根据接收到的内容更新数据表数据。如下图:
4),直接修改数据并完成提交。
根据下拉选项中的姓名数据,反向查询工作数据并更新,如下图