1 Django表单介绍
常见的表单元素:
- 表单标签——
<form>
- 单行文本框/多行文本框
- 选择(单选、多选、下拉选择)
- 隐藏表单域
- 表单按钮
- 文件上传框
Django中的表单:
- 框架自带
- Flask是使用FlaskWTF库
表单使用的步骤:
-
第一步:创建表单类
-
from django import forms class LoginForm(forms.Form): """ 登录表单 """ username = forms.CharField(label='用户名', max_length = 100)
-
-
第二步:添加到视图
-
views.py
-
def user_login(request): """ 用户登录 """ form = LoginForm() return render(request, 'user_login.html', { 'form':form })
-
urls.py
-
# 用户登录表单 path('user/login/', views.user_login, name='user_login'),
-
-
第三步:渲染到模板
-
as_p()
-
as_ul()
-
as_table()
-
<body> <h3>用户登录</h3> <form action="."> {{ form.as_p }} <input type="submit" value="登录"> </form> </body>
-
-
第四步:在视图中处理表单数据
-
<form action="." method="post">
-
def form(request): # 表单对象 if request.method == 'POST': form = LoginForm(request.POST) if form.is_valid(): data = form.cleaned_data print('data:',data) else: form = LoginForm() return render(request, 'form.html', { 'form':form })
-
表单字段
- 表单字段继承自 django.forms.Field
- 每个字段都具有核心参数
- 每个字段都可以有自定义的验证逻辑
- 每个字段都有钩子函数,方便扩充功能
字段的常用参数:
- label——label标签(如:输入框前的文字描述)
- required——是否为必填,默认为必填
- help_text——帮助文字
- initial——初始化数据
- error_messages——覆盖字段引发异常后的错误显示
- widget——定制界面显示方式(如:文本框、选择框)
- disabled——禁用表单,界面上不可操作
2 Django内置的表单字段
- 文本/字符串
- CharField——字符串输入
- EmailField——邮件地址输入
- URLField——URL地址输入
- UUIDField——uuid字符串输入
- 数值(整数/小数)
- IntegerField——整数输入
- FloatField——浮点数输入
- DecimalField——小数输入(更精确)
- 选择(单选/多选)
- ChoiceField——单选
- MultipleChoiceField——多选
- TypedChoiceField——高级选择(支持结果转换类型)
- 日期/时间
- DateField——日期选择
- DateTimeField——日期时间选择
- DurationField——时间片段timedelta
- TimeField——时间选择
- 文件/文件上传
- ImageField——图片
- FileField——文件
- FilePathField——文件路径
- 布尔
- BooleanField——True/False
- NullBooleanField——None/True/False
- 正则表达式
- RegexField——正则输入
3 Django创建用户注册表单
设计注册表单:
- 用户名
- 密码
- 用户昵称
- 生日
在视图中获取表单值:
- GET请求
request.GET.get('name', None)
- POST请求
request.POST.get('name', None)
- 文件对象
request.FILES.get('name', None)
表单类的可选参数:
-
initial——初始化参数
-
def user_reg(request): """ 用户注册 """ if request.method == 'POST': data = request.POST print('post data:',data) initial_data = { 'username':'默认昵称', 'birth_data':'2000-1-1' } form = UserRegForm(initial=initial_data) return render(request, 'user_reg.html',{ 'form':form })
-
-
data——表单数据
-
files——文件对象
Form对象的方法:
- as_p()/as_ul()/as_table()——渲染表单
- is_valid()——表单是否已经通过验证
- clean()——调用表单的验证/自定义的验证
- is_bound——是否已经绑定了属性
- cleaned_data——访问表单验证后的数据
- errors——表单验证后的错误信息
- initial——初始化数据
- fields——表单中的字段
def user_reg(request):
""" 用户注册 """
if request.method == 'POST':
data = request.POST
print('post data:',data)
form = UserRegForm(data=request.POST, files=request.FILES)
# 是否已经通过验证
if form.is_valid():
form_data = form.cleaned_data
print('验证通过后的数据:',form_data)
else:
# 表单没有通过验证
print(form.errors)
else:
initial_data = {
'username':'默认昵称',
'birth_date':'2000-1-1'
}
form = UserRegForm(initial=initial_data)
return render(request, 'user_reg.html',{
'form':form
})
4 自定义界面显示
- 密码输入
- URL输入、Email输入、日期输入等
- 多行文本输入
示例代码:
class CommentForm(forms.Form):
""" 评论表单 """
content = forms.CharField(
label = '内容',
widget = forms.Textarea
)
内置的widgets:
-
文本输入
- TextInput
- NumberInput
- EmailInput
- URLInput
- PasswordInput
- HiddenInput
- DateInput
- DateTimeInput
- TimeInput
- Textarea
-
选择输入
- Select
- NullBooleanSelect
- RadioSelect
- SelectMultiple
- CheckboxSelectMultiple
-
文件上传
- FileInput
-
复合Widget
- MultipleHiddenInput
- SplitDateTimeWidget、SplitHiddenDateTimeWidget
- SelectDateWidget
5 单个字段的表单验证
表单验证的步骤:
- 第一步:定义clean_xx验证方法
- 第二步:获取对应的字段值并验证
- 第三步:验证失败触发forms.ValidationError异常
- 第四步:返回验证后的数据
- 第五步:在html页面显示错误
forms.py
class LoginForm(forms.Form):
""" 登录表单 """
username = forms.CharField(label='用户名',
max_length=100,
required=False,
help_text='使用帮助',
initial='admin')
def clean_username(self):
""" 验证用户名 hook 钩子函数 """
username = self.cleaned_data['username']
pattern = r'^1[0-9]{10}$'
if not re.search(pattern, username):
raise forms.ValidationError('请输入手机号码')
return username
views.py
def user_login(request):
""" 用户登录 """
if request.method == 'POST':
form = LoginForm(data=request.POST)
if form.is_valid():
print('表单验证通过')
else:
print(form.errors)
else:
form = LoginForm()
return render(request, 'user_login.html', {
'form': form
})
6 多个字段的综合验证
- 第一步:重写 clean()方法
- 第二步:获取用户名和密码数据并验证
- 第三步:验证失败触发 forms.ValidationError异常
- 第四步:返回验证后的表单数据 cleaned_data
- 第五步:在html页面显示错误 non_filed_errors
class LoginForm(forms.Form):
""" 登录表单 """
username = forms.CharField(label='用户名',
max_length=100,
required=False,
help_text='使用帮助',
initial='admin')
password = forms.CharField(label='密码', max_length=200, min_length=6,
widget=forms.PasswordInput)
def clean_username(self):
""" 验证用户名 hook 钩子函数 """
username = self.cleaned_data['username']
pattern = r'^1[0-9]{10}$'
if not re.search(pattern, username):
raise forms.ValidationError('手机号%s输入不正确',
code='invalid_phone',
params=(username, ))
return username
def clean(self):
data = super().clean()
print(data)
# 如果单个字段有错误,直接返回,不执行后面的验证
if self.errors:
return
username = data['username']
password = data['password']
# username = data.get('username', None)
# password = data.get('password', None)
if username and password:
# 查询用户名和密码匹配的用户
user_list = User.objects.filter(username=username)
err_list = []
if user_list.count() == 0:
err_list.append(forms.ValidationError('用户名不存在'))
# raise forms.ValidationError('用户名不存在')
# 验证密码是否正确
# TODO 使用加密算法进行验证
if not user_list.filter(password=password).exists():
# raise forms.ValidationError('密码不正确')
err_list.append(forms.ValidationError('密码不正确'))
if err_list:
raise forms.ValidationError(err_list)
return data
7 从ORM模型创建表单
ORM模型VS表单模型:
models.py
class User(CommonModel):
""" 用户基本信息 """
USER_STATUS = (
(1, '正常'),
(0, '删除'),
)
username = models.CharField('用户名', max_length=128, unique=True, editable=False)
password = models.CharField('密码', max_length=256)
nickname = models.CharField('用户昵称', max_length=256, null=True, blank=True)
avatar = models.ImageField('用户头像', upload_to='avatar', null=True, blank=True)
status = models.SmallIntegerField('用户状态', default=1, choices=USER_STATUS)
is_super = models.BooleanField('是否为超级用户', default=False)
created_at = models.DateTimeField('注册时间', auto_now_add=True)
updated_at = models.DateTimeField('更新时间', auto_now=True)
# users = models.Manager()
class Meta:
db_table = 'accounts_user'
def __str__(self):
return 'User: {}'.format(self.username)
forms.py
class UserChangeForm(forms.ModelForm):
""" 从模型创建表单 -- 用户基本信息修改 """
class Meta:
model = User
# fields = ('username', 'password', 'nickname', 'avatar')
exclude = ('status', )
views.py
def user_change(request):
""" 用户信息维护-基于ORM创建的表单 """
if request.method == 'POST':
form = UserChangeForm(data=request.POST)
if form.is_valid():
print('表单通过验证')
else:
form = UserChangeForm()
return render(request, 'user_change.html', {
'form': form
})