在之前Django初识(3.常用视图之ListView视图)中我们提到了有五大常用视图,其中要实现增这样一个操作会用到CreateView视图,表格中还提到使用CreateView同时需要Model和Form,那么我们首先来看一下Form。
Form主要分为两种:
- Form(数据要手动验证,手动定义每个字段,跟Model无关)
- ModelForm(会一对一关联的model类名,直接使用Model中所定义的字段)
Form
配置forms.py文件
forms.py文件主要就是存放form相关的东西,不管是使用普通的form还是ModelForm都是在里面编写form代码。
from django import forms
class CreatePersonForm(forms.Form):
name = forms.CharField(max_length=32)
age = forms.IntegerField()
gender = forms.BooleanField()
id_card = forms.IntegerField()
address = forms.CharField(max_length=255)
temperature = forms.FloatField()
可以看到普通form编写其实是和model基本相同,唯一不同的就是model中使用models.###,而form中使用forms.###。
在终端中的一些操作
和model相同,我们也可以在终端中导入form来进行操作,同样的需要运行python manage.py shell 进入命令交互界面,然后导入我们需要操作的Form类:
from Django01_app02.forms import CreatePersonForm
在终端中先实例化出来一个form,给form赋值
>>> form=CreatePersonForm(data={'name':'王二狗','age':15,'gender':2,'id_card':123456789,'address':''})
>>> form
<CreatePersonForm bound=True, valid=Unknown, fields=(name;age;gender;id_card;address;temperature)>
在上面我们并没有给form所有参数进行赋值,而且当我们查看form时发现里面bound=True,valid=Unknow,意思是说我们成功的data数据传入form中,但是还没有验证。我们进行手动验证,利用form.is_valid()就可以验证数据了。
>>> form.is_valid()
False
>>> form
<CreatePersonForm bound=True, valid=False, fields=(name;age;gender;id_card;address;temperature)>
验证过之后出现了False,再来查看form时发现里面valid=False,表明我们并没有验证成功,这是为什么呢,利用form.errors查看错误,发现是因为刚才我们在赋值的时候没有填写address,temperature所以验证不通过。
>>> form.errors
{'address': ['This field is required.'], 'temperature': ['This field is required.']}
通常遇到验证不通过的情况就需要我们执行另外的操作,把它抛出异常或者是把异常渲染到前端,接着我们把form中验证未通过的两个参数赋值,之后进行验证便可成功通过,并且没有错误信息。之后便可以在视图里面进行数据的保存以及返回到某一个页面。
>>> form=CreatePersonForm(data={'name':'王二狗','age':15,'gender':2,'id_card':123456789,'address':'北京市','temperature':37})
>>> form
<CreatePersonForm bound=True, valid=Unknown, fields=(name;age;gender;id_card;address;temperature)>
>>> form.is_valid()
True
>>> form
<CreatePersonForm bound=True, valid=True, fields=(name;age;gender;id_card;address;temperature)>
>>> form.errors
{}
需要注意的是:因为form和model没关系,所以即使是在form中验证成功了,在保存数据的时候依旧回报错,form中验证的是写在form中的限定条件,这个条件不一定和model中的一致,就比如我们现在gender=2,form并没有验证出来错误,但是在model中上传数据时因为限定了gender只能为1或0,所以就会报错。
编写Views(利用View)
定义get方法获取到页面(利用render函数渲染页面)
class PersonCreate(View):
def get(self, request, *args, **kwargs):
return render(request, 'Django01_app02/peraon_craete.html')
def post(self, request, *args, **kwargs):
#验证数据
data = request.POST
form =CreatePersonForm(data=data)
if form.is_valid():
#保存数据
person=Person(
name=form.cleaned_data['name'],
age=form.cleaned_data['age'],
gender=form.cleaned_data['gender'],
id_card=form.cleaned_data['id_card'],
address=form.cleaned_data['address'],
temperature=form.cleaned_data['temperature'],
)
person.save()
else:
raise Exception
#跳转
return HttpResponseRedirect(reverse('personal:peraon_list'))
编写Html
form中action,url反向解析,method可以提交(post)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登记人员信息</title>
</head>
<body>
<form action='{% url 'personal:peraon_create' %}' method="post">
{# <form action='' method="post">#}
{# 两者效果相同 action不填就默认为提交到当前的页面,但暂时不知道加上参数与不加的区别#}
{% csrf_token %}
<p><label>名字:<input type="text" name="name"></label></p>
<p><label>年龄:<input type="number" name="age"></label>
<p><label>性别:<select name="gender">
<option>请选择</option>
<option value="1">男</option>
<option value="0">女</option>
</select></label></p>
<p><label>身份证:<input type="number" name="id_card"></label></p>
<p><label>地址:<input type="text" name="address"></label></p>
<p><label>体温:<input type="number" name="temperature" step="0.1"></label></p>
<p><button type="submit">保存</button></p>
</form>
</body>
</html>
urls
#Django01_app02/urls.py
from django.urls import path
from Django01_app02.views import *
app_name='Django01_app02'
urlpatterns = [
path('list/', PersonList.as_view(),name='peraon_list'),
path('craete/', PersonCreate.as_view(),name='peraon_create')
]
?完成所有操作后我们便可以运行程序来打开页面,当然首先我们跳转到的是person_list的页面,那么怎样从person_list页面跳转到person_create页面,只需要在person_list.html中table表单下加上一句代码即可
<p><a href={% url 'personal:peraon_create' %}>登记</a></p>
?结果如下:
?点击登记按钮跳转到:
?然后我们可以填写,点击保存再次跳转到list界面并显示出刚才保存的信息。
ModelForm
????????在写表单的时候,会发现表单中的Field和模型中的Field基本上是一模一样的。而且一般情况下表单中需要验证的数据就是我们模型中需要保存的数据。那么这个时候我们就可以将模型中的字段和表单中的字段进行绑定
????????比如我们的数据库中有这样一张疫情人员信息表,字段有姓名,年龄,性别,住址,体温,等等一大堆信息,现在让你写一个创建疫情人员信息的页面,你的后台应该怎么写呢?
- ? ? 前端:首先会在前端一个一个罗列出这些字段,让用户去填写,然后后台一个一个接收用户的输入
- ? ? 后台:定义一个疫情人员模型,用来保存疫情人员信息
- ? ? 后台:定义一个疫情人员表单,用来验证前端传递过来的数据
- ? ? 后台:在视图函数中使用get()方法来一个一个的获取已通过验证的数据,然后使用模型中的QuerySet方法将数据保存起来
????????我们在上面就是使用的普通Form来进行的,但是在上面示例中:其实表单的定义和模型的定义其实是差不多的,但是如果按照上面这种方式来的话,一个差不多的东西我们就需要完整的定义两边,这样就显得混麻烦了
????????因此Django就提供了ModelForm组件:这个组件主要就是用来整合表单和模型,将它们两个连接起来使用。就不需要完整的定义两次了
配置forms.py文件
1. 必须继承forms.ModelForm
2. class Meta:
- model = "????????#一对一关联的model类名"
- fields = "__all__"? ? ? ? #表示model类里面所有的字段都展示(需要验证),也可以自定义字段
- exclude=None,? ? ? ? ? # 排除字段 ? ? ?(被排除的字段不需要需要验证)
- widgets=None, ? ? ? ? ?# 自定义插件 ? ? ?
- error_messages=None, ? ?# 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)
- labels=None, ? ? ? ? ? ? ? ? ? ? # 提示信息
- help_texts=None, ? ? ? ? ? ? ? ? # 帮助提示信息
- localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据
要想使用modelform,也必须先写个modelform
class PersonCreateForm(forms.ModelForm):
class Meta:
model = Person
fields='__all__'
配置Views(利用CreatView)
class PersonCreate(CreateView):
form_class = PersonCreateForm
model = Person
template_name = 'Django01_app02/peraon_craete.html'
success_url = reverse_lazy('personal:peraon_list')
编写Html
不需要自定义form表单,在html中用{{ form }}即可展示表单。加上.as_p可以使表单中每个字段换行。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登记人员信息</title>
</head>
<body>
<form action='{% url 'personal:peraon_create' %}' method="post">
{% csrf_token %}
{{ form.as_p }}
<p><button type="submit">保存</button></p>
</form>
</body>
</html>
?运行结果如下:
但是由model自动生成的表单是和model中定义的字段相同是英文,这时我们就可以利用modelform中 class Meta里面的labels属性进行一个重命名的操作,只需要在 class Meta下添加如下代码即可。
labels= {'name':'姓名','age':'年龄','gender':'性别','id_card':'身份证','address':'地址','temperature':'体温'}
?修改完成后再此次运行:
?到此为止我们对CreatView视图以及Form,ModelForm有了初步了解。
|