django中提供了一个form表单的功能,这个表单可以用来验证数据的合法性还可以用来生成HTML代码
- 关于django form表单的使用:
- 创建一个forms.py的文件,放在指定的app当中,然后在里面写表单.
- 表单是通过类实现的,继承自forms.Form,然后在里面定义要验证的字段.
- 在表单中,创建字段跟模型是一模一样的,但是没有null=True或者blank=True等这几种参数了,有的参数是required=True/False.
- 使用is_valid()方法可以验证用户提交的数据是否合法,而且HTML表单元素的name必须和django中的表单的name保持一致,否则匹配不到.
- is_bound属性:用来表示form是否绑定了数据,如果绑定了,则返回True,否则返回False.
- cleaned_data:这个是在is_valid()返回True的时候,保存用户提交上来的数据.
普通表单
- 注册校验
- views.py
class Register(View):
def get(self, request):
# 表单渲染注册界面
form = RegisterForm()
return render(request, 'register/register.html',context={
'form':form,
})
def post(self, request):
# 表单校验数据
form = RegisterForm(request.POST)
# 如果数据正确
if form.is_valid():
return HttpResponse('注册成功')
# 若校验失败,则渲染注册界面
return render(request, 'register/register.html', context={
'form': form,
})
- form.py
from django import forms
# 普通表单校验
class RegisterForm(forms.Form):
username = forms.CharField(label="用户名",max_length=20,required=True)
password = forms.CharField(label="密码",max_length=20,min_length=6,
widget=forms.PasswordInput(attrs={'placeholder':'请输入长度为6-20位的密码'}),
error_messages = {
'max_length':'密码长度小于6位',
'min_length':'密码长度大于8位',
'required':'必须传入'
})
password_repeat = forms.CharField(label="请再次输入密码",max_length=20,min_length=6,
widget=forms.PasswordInput(attrs={'placeholder':'请输入长度为6-20位的密码'}),
error_messages = {
'max_length':'密码长度小于6位',
'min_length':'密码长度大于8位',
})
- register.html
{% block content %}
<form class="form-horizontal" method="post">
{% csrf_token %}
{{ form.as_p }}
{{ detail_form.as_p }}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-2 col-xs-2 ">
{% if student_id %}
<button type="submit" class="btn btn-default">更新</button>
{% else %}
<button type="submit" class="btn btn-default">保存</button>
{% endif %}
</div>
</div>
</form>
{% endblock %}
-
展示
image.png
模型表单
- 具体展示
from django import forms
from news.models import News, Tag
class NewsPubForm(forms.ModelForm):
"""
"""
# 创建模型时,允许为空,所以需要重写,定义不能为空
image_url = forms.URLField(label='文章图片url',
error_messages={"required": "文章图片url不能为空"})
# 限制tag_id范围,tag是外键指定的多个值的多选框,所以定义的字段类型为ModelChoiceField
tag = forms.ModelChoiceField(queryset=Tag.objects.only('id').filter(is_delete=False),
error_messages={"required": "文章标签id不能为空", "invalid_choice": "文章标签id不存在", }
)
class Meta: # 元数据信息
# 指定那个数据库模型来创建表单
model = News # 与数据库模型关联
# 需要关联的字段
# exclude 排除
# 此处tag 指的是文章分类的实例对象,并不是tag_id,会出问题
fields = ['title', 'digest', 'content', 'image_url', 'tag']
# 自定义报错信息(由于定义模型没有写,所以在此处写)
error_messages = {
'title': {
'max_length': "文章标题长度不能超过150",
'min_length': "文章标题长度大于1",
# 传入字符串为空和,传入为空格是有区别的
'required': '文章标题不能为空',
},
'digest': {
'max_length': "文章摘要长度不能超过200",
'min_length': "文章标题长度大于1",
'required': '文章摘要不能为空',
},
'content': {
'required': '文章内容不能为空',
},
}
- 学生信息修改
- views.py
class NewStudentEdit(View):
def get(self, request, student_id):
student = models.Student.objects.select_related('studentdetail','area').filter(is_delete=False,id=student_id).first()
# 用对象将form表单填充
form = StudentForm(instance=student)
try:
detail_form = StudentDetailForm(instance=student.studentdetail)
except:
# 说明该学生对象并未创建学生详情,
student_detail = models.StudentDetail()
student_detail.student = student
student_detail.save()
detail_form = StudentDetailForm(instance=student.studentdetail)
courses = models.Course.objects.all()
area = models.Area.objects.all()
return render(request,'students/new_edit.html',locals())
- form.py
# 模型表单校验
class StudentForm(forms.ModelForm):
class Meta:
model = Student
exclude = ['is_delete']
class StudentDetailForm(forms.ModelForm):
class Meta:
model = StudentDetail
exclude = ['is_delete']
- html
{% extends 'base/base.html' %}
{% block title %}
学生详情
{% endblock %}
{% block section %}
{{ section }}
{% endblock %}
{% block content %}
<form class="form-horizontal" method="post">
{% csrf_token %}
{{ form.as_p }}
{{ detail_form.as_p }}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-2 col-xs-2 ">
{% if student_id %}
<button type="submit" class="btn btn-default">更新</button>
{% else %}
<button type="submit" class="btn btn-default">保存</button>
{% endif %}
</div>
</div>
</form>
{% endblock %}
-
展示
image.png
-
自定义样式
{% extends 'base/base.html' %}
{% block title %}
学生详情
{% endblock %}
{% block section %}
{{ section }}
{% endblock %}
{% block content %}
<form class="form-horizontal" method="post">
{% csrf_token %}
{# 循环表单里每个字段 #}
{% for filed in form %}
<div class="form-group">
{# 渲染错误 #}
{% for err in filed.errors %}
<label class="control-label" for="{{ filed.id_for_label }}">{{ err }}</label>
{% endfor %}
<label for="{{ filed.id_for_label }}" class="col-sm-2 control-label">{{ filed.label }}</label>
<div class="col-sm-2">
{{ filed }}
</div>
</div>
{% endfor %}
# 未自定义样式
{{ detail_form.as_p }}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-2 col-xs-2 ">
{% if student_id %}
<button type="submit" class="btn btn-default">更新</button>
{% else %}
<button type="submit" class="btn btn-default">保存</button>
{% endif %}
</div>
</div>
</form>
{% endblock %}
- 展示
[图片上传中...(image.png-3de43e-1552226626511-0)]
自定义验证
class NewStudentAdd(View):
def post(self, request):
form = StudentForm(request.POST)
detail_form = StudentDetailForm(request.POST)
if form.is_valid() and detail_form.is_valid():
student = form.save()
# 加上commit=False,不会去真的保存数据库
# 因为还要加上外键关联对象
student_detail = detail_form.save(commit=False)
student_detail.student = student
student_detail.save()
return redirect(reverse('index:index'))
return render(request, 'students/new_edit.html', locals())
class NewStudentEdit(View):
def get(self, request, student_id):
student = models.Student.objects.select_related('studentdetail','area').filter(is_delete=False,id=student_id).first()
# 用对象将form表单填充
form = StudentForm(instance=student)
try:
detail_form = StudentDetailForm(instance=student.studentdetail)
except:
# 说明该学生对象并未创建学生详情,
student_detail = models.StudentDetail()
student_detail.student = student
student_detail.save()
detail_form = StudentDetailForm(instance=student.studentdetail)
courses = models.Course.objects.all()
area = models.Area.objects.all()
return render(request,'students/new_edit.html',locals())
def post(self, request, student_id):
student = models.Student.objects.select_related('studentdetail', 'area').filter(is_delete=False,
id=student_id).first()
# 用对象将form表单填充
form = StudentForm(request.POST, instance=student)
detail_form = StudentDetailForm(request.POST, instance=student.studentdetail)
if form.is_valid() and detail_form.is_valid():
form.save()
detail_form.save()
return redirect(reverse('index:index'))
return render(request, 'students/new_edit.html', locals())
-
展示
image.png
image.png
模型表单的单字段和多字段校验
# 模型表单校验
class StudentForm(forms.ModelForm):
class Meta:
model = Student
exclude = ['is_delete']
# 自定义单字段校验
def clean_name(self):
name = self.cleaned_data.get('name')
if not name[:-1].isdigit():
raise forms.ValidationError('输入用户名不能为数字')
return name
-
展示
image.png
网友评论