博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WEB框架Django之Form组件
阅读量:6157 次
发布时间:2019-06-21

本文共 17671 字,大约阅读时间需要 58 分钟。

Django的Form主要具有一下几大功能:

  • 生成HTML标签
  • 验证用户数据(显示错误信息)
  • HTML Form提交保留上次提交数据
  • 初始化页面显示内容

一 通过form实现校验字段功能

模型:models.py

class UserInfo(models.Model):        name = models.CharField(max_length=32)        pwd = models.CharField(max_length=32)        email = models.EmaillField()        tel = models.CharField(max_length=32)

模板:register.html

用户名

密码

确认密码

邮箱

手机号

{
% csrf_token %}

 

二 通过form组件对模板进行渲染

form校验组件

from django import formsclass UserForm(forms.Form):    username = forms.CharField(min_length=4)    password = forms.CharField(min_length=4)    repwd = forms.CharField(min_length=4)    email = forms.EmailField()    tel = forms.CharField

视图函数

def register(req):    if req.method == 'POST':    # form = UserForm({'name':'cs', 'email': '123@qq.com', 'xxx':'harry'})    form = UserForm(req.POST)       # 注意form表单的name属性值应该与forms组件字段名称一致    print(form.is_valid())  # 返回布尔值    if form.is_valid():          print(form.cleaned_data)    # {"name":'cs", "email:'123@qq.com'}    else:          print(form.cleaned_data)          print(form.errors)          # {"name":["......"]}
return  HttpResponse('ok')
'''if 所有的字段校验成功,则form.cleaned_data以一个字典的形式存放所有校验通过的数据                    '''    return render(req, "register.html")

form组件在模板中渲染

1 
2

3 用户名 {

{ form.username }} 4

5

6 密码 {

{ form.password }} 7

8

9 确认密码 {

{ form.repwd }}10

11

12 email {

{ form.email }}13

14

15 手机号 {

{ form.tel }}16

17
方式一
1 
2 {% csrf_token %}3 {% for filed in form %}4

5

{
{ filed.label }}
6 {
{ filed }}7

8 {% endfor %}9
方式二

 展示错误信息

{
% csrf_token %} {
% for filed in form %}

{
{ filed.label }}
{
{ filed }} {
{ filed.errors.0 }}

{
% endfor %}

三 form组件的配置参数

Filed参数            required=Ture                   是否必填            widget=None                     HTNL插件            label=None                      用于生成Label标签显示内容            initial=None                    初始值            help_text=''                    帮助信息(在标签旁边显示)            error_messages=None             错误信息{
'required':'不能为空’, 'invalid':'格式错误’} show_hidden_initial=False 是否在当前插件后再加一个隐藏的具有默认值的插件(可用于两次输入是否一致) validators=[], 自定义验证规则 localize=False 是否支持本地化 disabled=False 是否可以编辑 label_suffix=None Lable内容后缀 CharField(Field) max_length=None 最大长度 min_length=None 最小长度 strip=True 是否移除用户输入空白 IntergerField(Field) max_value = None 最大值 min_value = None 最小值 DecimalField(IntergerField) max_value=None 最大值 min_value=None 最小值 max_digits=None 总长度 decimal_places=None 小数位长度 BaseTemporalField(Field) input_forats=None 时间格式化 DateField(BaseTemporalField) 格式:2015-09-01 TimeField(BaseTemporalField) 格式:11:12 DateTimeField(BaseTemporalField) 格式:2015-09-01 11:12 RegexField(charField) regex, 自定义正则表达式 max_length=None, 最大长度 min_length=None, 最小长度 error_message=None {
"invalid":"..."} FileField(Field) allow_empty_file=False 是否允许空文件 ChoiceField(Field) choices=(), 选项,如:choices = ((0,'上海’),(1,,'北京') required=True 是否必填 widget=None 插件,默认select插件 label=None Label内容 initial=None 初始值 help_text='', 帮助提示 TypeChoiceField(ChoiceField) coerce = lambda val: val 对选中的值进行一次转换 empty_value = '' 空的默认值 ComboFiel(Field) fields=() 使用多个验证,如下:即验证最大程度20,又验证邮箱格式 fields.ComboField(fields=[fields.CharField(max_length=20),fields.EmailField(),] GenericIPAddressField protocol='both', both,ipv4,ipv6支持的IP格式 unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.0.2.1 可以解析为192.0.0.2.1 SlugField(CharField) 数字,字母,下划线,减号(连接符)

在form中使用组件

from  django.core.exceptions import NON_FIELD_ERRORS,ValidationErrorclass UserForm(forms.Form):        username = forms.CharField(min_length=2, label='用户名',              error_messages={
"required": "该字段不能为空"},              widget= widgets.TextInput(attrs={
'class':"form-control"})) password = forms.CharField(min_length=4,                      label='密码',                      widget=widgets.PasswordInput(attrs={
'class':"form-control"})) repwd = forms.CharField(min_length=4,                    label='重复密码',                    widget= widgets.TextInput(attrs={
'class':"form-control"})) email = forms.EmailField(label='邮箱',                     error_messages={
"required": "该字段不能为空", "invalid":"格式输入错误"},     widget= widgets.TextInput(attrs={
'class': "form-control"})) tel = forms.CharField(label="电话号码",                      error_messages={
"required": "该字段不能为空"}, widget=widgets.TextInput(attrs={
'class': "form-control"})) def clean_username(self): val = self.cleaned_data.get("username") # 获取输入的名字 ret = UserInfo.objects.filter(name=val) # 从数据库中查询是否有该用户存在if not ret: return val else: raise ValidationError("该用户已注册") def clean_tel(self): var = self.cleaned_data.get("tel") if len(var) == 11: return var else: raise ValidationError("手机号码必须为11位!") def clean(self): pwd = self.cleaned_data.get("password") r_pwd = self.cleaned_data.get("repwd") if pwd and r_pwd: if pwd == r_pwd: return self.cleaned_data else: raise ValidationError('两次密码不一致') else: return self.cleaned_data

 在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 ***获取的值无法实时更新***,那么需要自定义构造方法从而达到此目的。

方式一:

1 from django.forms import Form 2 from django.forms import widgets 3 from django.forms import fields 4 from django.core.validators import RegexValidator 5   6 class MyForm(Form): 7   8     user = fields.ChoiceField( 9         # choices=((1, '上海'), (2, '北京'),),10         initial=2,11         widget=widgets.Select12     )13  14     def __init__(self, *args, **kwargs):15         super(MyForm,self).__init__(*args, **kwargs)16         # self.fields['user'].widget.choices = ((1, '上海'), (2, '北京'),)17         # 或18         self.fields['user'].widget.choices = models.Classes.objects.all().value_list('id','caption')

方式二:

使用django提供的ModelChoiceField和ModelMultipleChoiceField字段来实现

1 from django import forms 2 from django.forms import fields 3 from django.forms import widgets 4 from django.forms import models as form_model 5 from django.core.exceptions import ValidationError 6 from django.core.validators import RegexValidator 7   8 class FInfo(forms.Form): 9     authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())10     # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())

 

四 自定义验证规则

方式一 使用字段钩子或者全局钩子

from  django.core.exceptions import NON_FIELD_ERRORS,ValidationErrorclass UserForm(forms.Form):        username = forms.CharField(min_length=2,                      label='用户名',                      error_messages={
"required": "该字段不能为空"},                      widget=widgets.TextInput(attrs={
'class':"form-control"})) password = forms.CharField(min_length=4,                      label='密码',                      widget=widgets.PasswordInput(attrs={
'class':"form-control"})) repwd = forms.CharField(min_length=4,                      label='重复密码',                      widget= widgets.TextInput(attrs={
'class':"form-control"})) email = forms.EmailField(label='邮箱',                     error_messages={
"required": "该字段不能为空", "invalid":"格式输入错误"}, widget=widgets.TextInput(attrs={
'class': "form-control"})) tel = forms.CharField(label="电话号码",                  error_messages={
"required": "该字段不能为空"}, widget=widgets.TextInput(attrs={
'class': "form-control"})) def clean_username(self): val = self.cleaned_data.get("username") # 获取输入的名字 ret = UserInfo.objects.filter(name=val) # 从数据库中查询是否有该用户存在if not ret: return val else: raise ValidationError("该用户已注册") def clean_tel(self): var = self.cleaned_data.get("tel") if len(var) == 11: return var else: raise ValidationError("手机号码必须为11位!") def clean(self): pwd = self.cleaned_data.get("password") r_pwd = self.cleaned_data.get("repwd") if pwd and r_pwd: if pwd == r_pwd: return self.cleaned_data else: raise ValidationError('两次密码不一致') else: return self.cleaned_data

 方式二 使用validators参数进行正则表达式匹配

1 from django.forms import Form2 from django.forms import widgets3 from django.forms import fields4 from django.core.validators import RegexValidator5  6 class MyForm(Form):7     user = fields.CharField(8         validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],9     )

通过正则表达式验证IP地址以及端口号

ipaddr_validate="^((?:(2[0-4]\d)|(25[0-5])|([01]?\d\d?))\.){3}(?:(2[0-4]\d)|(255[0-5])|([01]?\d\d?))$"port_validate='^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$'
from django.forms import Form,fieldsfrom django.forms import widgets,formsimport reipaddr_validate="^((?:(2[0-4]\d)|(25[0-5])|([01]?\d\d?))\.){3}(?:(2[0-4]\d)|(255[0-5])|([01]?\d\d?))$"port_validate='^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$'class dbinfo_create(Form):    data_mode_type=fields.CharField(required=True,error_messages={
'required':'数据库模型不能为空.'}) database_type=fields.CharField(required=True,error_messages={
'required':'数据库类型不能为空'}) host=fields.RegexField(ipaddr_validate,required=True,error_messages={
'required':'IP不能为空','invalid':'不合法的IP地址'}) port=fields.RegexField(port_validate,required=True,error_messages={
'required':'端口不能为空.','invalid':'端口无效'}) # instance_nikename=fields.CharField(max_length=20,error_messages={'required':'端口不能为空.',"max_length":"标题不能超过20个字"}) db_business=fields.CharField(required=True,error_messages={
'required':'请说明所属业务线'}) DBA=fields.CharField(required=True,error_messages={
'required':'请说明DBA'}) responsible_person=fields.CharField(required=True, error_messages={
'required':'请选择相关责任人!'})

五 通过Ajax提交并验证表单

注册新用户

{% csrf_token %}

用户名:{

{ form_obj.username }}

密码:{

{ form_obj.password }}

确认密码:{

{ form_obj.re_pwd }}

Emil:{

{ form_obj.email }}

验证码{

{ form_obj.check_code }}

HTML
function bindSubmit() {        $('#submit_info').click(function () {            $("#form p").removeClass('has-error');            $(".errors").html('');            var subData = new FormData();            var request_data = $('#form').serializeArray();            $.each(request_data, function (index, data) {                subData.append(data.name, data.value);            });            subData.append("avatar", $('#avatar')[0].files[0]);            subData.append('csrfmiddlewaretoken', $("[name='csrfmiddlewaretoken']").val());            $.ajax({                url: "/register/",                type: "post",                processData: false,                contentType: false,                data: subData,                dataType: 'json',                success: function (data) {                    console.log(data.error_msg);                    if (!data.state) {                        if (data.summary_error) {                            $('#summary-error').html(data.summary_error)                        }                        $.each(data.error_msg, function (field, msg) {                            if (field == "__all__") {                                $('#summary-error').html(msg[0]).parent().addClass("has-error")                            }                            $('#id_' + field).next().html(msg[0]).addClass('errors').parent().addClass('has-error')                        })                    } else {                        console.log(123);                        location.href = '/index/'                    }                }            })        })    }
JS
class RegisterForm(forms.Form):    '''    注册form表单校验    '''    username = forms.CharField(        max_length=32,        error_messages={
'required': '用户名不能为空'}, widget=widgets.TextInput(attrs={
'class': "form-control"})) password = forms.CharField( max_length=32, error_messages={
'required': '密码不能为空'}, widget=widgets.PasswordInput(attrs={
'class': "form-control"})) re_pwd = forms.CharField( max_length=32, error_messages={
'required': '密码不能为空'}, widget=widgets.PasswordInput(attrs={
'class': "form-control"})) email = forms.EmailField( error_messages={
'required': '邮箱不能为空'}, widget=widgets.EmailInput(attrs={
'class': "form-control"})) check_code = forms.CharField( widget=widgets.TextInput(attrs={
'class': "form-control"})) def clean_username(self): ''' 校验用户是否存在 :return: ''' username = self.cleaned_data.get('username') user_obj = models.UserInfo.objects.filter(username=username) if not user_obj: return username else: raise ValidationError('该用户已存在') def clean(self): ''' 校验两次输入的密码是否一致 :return: ''' password = self.cleaned_data.get('password') repwd = self.cleaned_data.get('re_pwd') if password == repwd: return self.cleaned_data else: raise ValidationError("两次密码输入不一致") def clean_email(self): ''' 校验注册邮箱是否已经注册 :return: ''' email = self.cleaned_data.get('email') user_obh = models.UserInfo.objects.filter(email=email) if not user_obh: return email else: raise ValidationError("该邮箱已被注册")
form.py
def register(request):    '''    通过ajax实现用户注册    :param request:    :return:    '''    response = {
'state': False, 'error_msg':"", 'summary_error': ""} if request.is_ajax(): form_obj = blog_forms.RegisterForm(request.POST) if form_obj.is_valid(): username = form_obj.cleaned_data.get('username') password = form_obj.cleaned_data.get('password') Email = form_obj.cleaned_data.get('email') valid_code = form_obj.cleaned_data.get('check_code') avatar_obj = request.FILES.get('avatar') check_valid = request.session['valid_code'] if valid_code == check_valid: extra = {} if avatar_obj: extra["avatar"] = avatar_obj blog_obj = models.Blog.objects.create( title="%s的博客" % username, site_name="%s的个人站点" % username, theme="default.css") models.UserInfo.objects.create_user(username=username, password=password, blog=blog_obj, email=Email, **extra) response['state'] = True return JsonResponse(response) else: response['summary_error'] = '验证码错误' return JsonResponse(response) else: response['error_msg'] = form_obj.errors return JsonResponse(response) elif request.method == 'GET': form_obj = blog_forms.RegisterForm() return render(request, 'register.html', {
'form_obj': form_obj})
View.py

 

转载于:https://www.cnblogs.com/harryblog/p/9350818.html

你可能感兴趣的文章
小白都能玩的算法day2-数量级、输入和输出
查看>>
『中级篇』Docker Cloud自动构建 Docker image(55)
查看>>
Java多线程编程笔记4:Java内存模型
查看>>
《Linux》阿里云部署django全攻略
查看>>
Java 原子类的操作 AtomicInteger
查看>>
浅谈HTTP缓存
查看>>
JVM 类加载机制
查看>>
深入理解幂等技术
查看>>
什么是自然语言处理技术
查看>>
stream pipe的原理及简化源码分析
查看>>
angular5.0封装underscore常用pipe并发布到npm全套流程
查看>>
Linux搭建私有Git服务器以及ssh免密登陆配置
查看>>
flask学习笔记之flask-migrate
查看>>
个推微服务网关架构实践
查看>>
【译】LiveData 在 SnackBar/Navigation 情景下的使用(SingleLiveEvent)
查看>>
终端报错"xcrun: error: unable to find utility “xcodebuild”, not a developer tool or
查看>>
百度地图发布“高考考点地图”,为考生开启“静音”模式
查看>>
Linux中如何运行.AppImage文件
查看>>
由奥迪车灯想到的前端动画
查看>>
TypeScript--es5中的类,继承,静态方法
查看>>