Django的Form表单

Django Form 

Form介绍

Form 表单是在前端向后端提交数据最常用的方式,同时在好多场景下都需要对用户的输入进行校验。

以注册为例,Form 需要的三件事:

  1. 要有一个注册的页面,页面里面要有form表单
    生成HTML代码

  2. form表单要能提交数据到后端,后端要做有效性校验
    数据有效性校验

  3. 要把校验的提示信息展示在页面上
    校验信息返回并展示,保存原来填写的内容

普通方式的注册功能

视图函数

# 注册
def register(request):error_msg = ""if request.method == "POST":username = request.POST.get("name")pwd = request.POST.get("pwd")# 对注册信息做校验if len(username) < 6:# 用户长度小于6位error_msg = "用户名长度不能小于6位"else:# 将用户名和密码存到数据库return HttpResponse("注册成功")return render(request, "register.html", {"error_msg": error_msg})

模板

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>注册页面</title>
</head>
<body>
<form action="/reg/" method="post">{% csrf_token %}<p>用户名:<input type="text" name="name"></p><p>密码:<input type="password" name="pwd"></p><p><input type="submit" value="注册"><p style="color: red">{{ error_msg }}</p></p>
</form>
</body>
</html>

Django 的 Form 组件

所以,Django 的 Form 组件对应上面所提三件事:

  1. 生成页面可用的HTML标签

  2. 对用户提交的数据进行校验

  3. 保留上次输入内容

创建 Form 类

创建 Form 类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成 HTML;

要导入的包:

  • from django import forms
    这是 Form 组件的父类,用于创建 Form 类

  • from django.forms import widgets
    用于对每个字段指定样式

字段与插件

initial 初始值

初始值,input 框里面的初始值

class RegForm(forms.Form):username = forms.CharField(min_length=8,label="用户名",initial="张三"# 设置默认值)pwd = forms.CharField(min_length=6, label="密码")

error_messages

重写错误信息。

class RegForm(forms.Form):name = forms.CharField(# 校验规则相关max_length=16,label="用户名",error_messages={"required": "该字段不能为空","invalid": "格式错误","man_length": "用户名最长16位"},# widget控制的是生成HTML代码相关的规则widget=widgets.TextInput(attrs={"class": "form-control"}))

password

  • render_value=True 提交后输入框内容依然存在
class RegForm(forms.Form):……pwd = forms.CharField(label="密码",min_length=6,max_length=10,# render_value=True 提交后输入框内容依然存在widget=widgets.PasswordInput(attrs={"class": "form-control"}, render_value=True),error_messages={"min_length": "密码不能少于6位!","max_length": "密码最长10位!","required": "该字段不能为空!"})

radioSelect

单radio值为字符串

class RegForm(forms.Form):……gender = forms.fields.ChoiceField(choices=((1, "男"), (2, "女"), (3, "保密")),label="性别",initial=3,widget=forms.widgets.RadioSelect())

单选 Select

class RegForm(forms.Form):...hobby = forms.fields.ChoiceField(choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),label="爱好",initial=3,widget=forms.widgets.Select())

多选 Select

class RegForm(forms.Form):...hobby = forms.fields.MultipleChoiceField(choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),label="爱好",initial=[1, 3],widget=forms.widgets.SelectMultiple())

单选 checkbox

class RegForm(forms.Form):...keep = forms.fields.ChoiceField(label="是否记住密码",initial="checked",widget=forms.widgets.CheckboxInput())

多选 checkbox

class RegForm(forms.Form):...hobby = forms.fields.MultipleChoiceField(choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),label="爱好",initial=[1, 3],widget=forms.widgets.CheckboxSelectMultiple())

Django Form 所有内置字段

Fieldrequired=True,               是否允许为空widget=None,                 HTML插件label=None,                  用于生成Label标签或显示内容initial=None,                初始值help_text='',                帮助信息(在标签旁边显示)error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}validators=[],               自定义验证规则localize=False,              是否支持本地化disabled=False,              是否可以编辑label_suffix=None            Label内容后缀CharField(Field)max_length=None,             最大长度min_length=None,             最小长度strip=True                   是否移除用户输入空白IntegerField(Field)max_value=None,              最大值min_value=None,              最小值FloatField(IntegerField)...DecimalField(IntegerField)max_value=None,              最大值min_value=None,              最小值max_digits=None,             总长度decimal_places=None,         小数位长度BaseTemporalField(Field)input_formats=None          时间格式化   DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12DurationField(Field)            时间间隔:%d %H:%M:%S.%f...RegexField(CharField)regex,                      自定制正则表达式max_length=None,            最大长度min_length=None,            最小长度error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'}EmailField(CharField)      ...FileField(Field)allow_empty_file=False     是否允许空文件ImageField(FileField)      ...注:需要PIL模块,pip3 install Pillow以上两个字典使用时,需要注意两点:- form表单中 enctype="multipart/form-data"- view函数中 obj = MyForm(request.POST, request.FILES)URLField(Field)...BooleanField(Field)  ...NullBooleanField(BooleanField)...ChoiceField(Field)...choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)required=True,             是否必填widget=None,               插件,默认select插件label=None,                Label内容initial=None,              初始值help_text='',              帮助提示ModelChoiceField(ChoiceField)...                        django.forms.models.ModelChoiceFieldqueryset,                  # 查询数据库中的数据empty_label="---------",   # 默认空显示内容to_field_name=None,        # HTML中value的值对应的字段limit_choices_to=None      # ModelForm中对queryset二次筛选ModelMultipleChoiceField(ModelChoiceField)...                        django.forms.models.ModelMultipleChoiceFieldTypedChoiceField(ChoiceField)coerce = lambda val: val   对选中的值进行一次转换empty_value= ''            空值的默认值MultipleChoiceField(ChoiceField)...TypedMultipleChoiceField(MultipleChoiceField)coerce = lambda val: val   对选中的每一个值进行一次转换empty_value= ''            空值的默认值ComboField(Field)fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])MultiValueField(Field)PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用SplitDateTimeField(MultiValueField)input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中path,                      文件夹路径match=None,                正则匹配recursive=False,           递归下面的文件夹allow_files=True,          允许文件allow_folders=False,       允许文件夹required=True,widget=None,label=None,initial=None,help_text=''GenericIPAddressFieldprotocol='both',           both,ipv4,ipv6支持的IP格式unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用SlugField(CharField)           数字,字母,下划线,减号(连字符)...UUIDField(CharField)           uuid类型Django Form内置字段

生成 HTML 页面

方式一:自动填写

在模板文件 form 中,加入 {{ form_obj.as_p }} 就可以自动生成了。

优点:方便
缺点:不能添加 CSS 样式

<form action="/reg/" method="post" novalidate> {% csrf_token %}  {{ form_obj.as_p }} <input type="submit" value="提交">
</form>

方式二:逐个手写

优点:能够为各个标签添加 CSS 样式类,也可以使用 Bootstrap 样式类等
缺点:代码量较大

<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
{#方式二:逐个填充,可以填充样式#}
<div class="container"><div class="row"><div class="col-md-6 col-md-offset-3"><form action="/reg/" method="post" novalidate>{% csrf_token %}<div class="form-group {% if form_obj.name.errors.0 %} has-error {% endif %}">{{ form_obj.name.label }}{{ form_obj.name }}<span class="help-block">{{ form_obj.name.errors.0 }}</span></div><div class="form-group {% if form_obj.pwd.errors.0 %} has-error {% endif %}">{{ form_obj.pwd.label }}{{ form_obj.pwd }}<span class="help-block">{{ form_obj.pwd.errors.0 }}</span></div><div class="form-group {% if form_obj.re_pwd.errors.0 %} has-error {% endif %}">{{ form_obj.re_pwd.label }}{{ form_obj.re_pwd }}<span class="help-block">{{ form_obj.re_pwd.errors.0 }}</span></div><div class="form-group {% if form_obj.email.errors.0 %} has-error {% endif %}">{{ form_obj.email.label }}{{ form_obj.email }}<span class="help-block">{{ form_obj.email.errors.0 }}</span></div><div class="form-group {% if form_obj.mobile.errors.0 %} has-error {% endif %}">{{ form_obj.mobile.label }}{{ form_obj.mobile }}<span class="help-block">{{ form_obj.mobile.errors.0 }}</span></div><div class="form-group {% if form_obj.city.errors.0 %} has-error {% endif %}">{{ form_obj.city.label }}{{ form_obj.city }}<span class="help-block">{{ form_obj.city.errors.0 }}</span></div><div class="form-group"><input type="submit" class="btn btn-default"></div></form></div></div>
</div>

form2

校验

做校验

通过函数 is_valid 做校验,校验后的各种字段数据会保存在 form_obj.clean_data 中。

    if request.method == "POST":# 更新form_obj的内容form_obj = RegForm(request.POST)# form自己可以做校验if form_obj.is_valid():# 1. form_obj.cleaned_data存储form校验后的内容,需要在is-valid函数后使用del form_obj.cleaned_data["re_pwd"]

在模板页面,使用 Form实例.字段名.errors.0的方式来显示后端发来的校验信息。

<div class="form-group {% if form_obj.name.errors.0 %} has-error {% endif %}">{{ form_obj.name.label }}{{ form_obj.name }}<span class="help-block">{{ form_obj.name.errors.0 }}</span>
</div>

Form 类自带校验字段

Form 类设置的各种字段的值自动包含所要校验的内容,而校验结果显示的信息放在 error_messages 字段中。

re_pwd = forms.CharField(label="确认密码",min_length=6,max_length=10,widget=widgets.PasswordInput(attrs={"class": "form-control"}, render_value=True),error_messages={"min_length": "密码不能少于6位!","max_length": "密码最长10位!","required": "该字段不能为空!"})

Form 自带的正则校验

除了 Form 类中的字段能够校验外,还需要根据需求自定义校验,其中,正则校验就是一个比较常用的校验方式, Form 类中自带正则校验方法。

from django import forms
from django.forms import widgets
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationErrormobile = forms.CharField(label="手机",# 自己定制校验规则validators=[RegexValidator(r'^[0-9]+$',"手机号必须是数字"),RegexValidator(r'^1[3-9][0-9]{9}$', "手机格式不正确")],widget=widgets.TextInput(attrs={"class": "form-control"}),error_messages={"required": "该字段不能为空"})

具体字段的自定义校验方法

在 Form 类中加上 clean_XX 函数,可在其中自定义对 XX 字段的校验。这种方法只能使用此字段。

在此函数中,

  • 如果校验出错,通过 raise ValidationError("错误提示信息") 方式抛出提示信息
  • 函数的最后,即校验成功,返回该字段, return XX
def clean_name(self):name = self.cleaned_data.get("name")if "中国" in name:raise ValidationError("不要脸")   return name

全局的自定义校验方法

在 Form 类中,重写 clean 函数,可以实现对多个字段的自定义校验。

添加提示信息的方法:

self.add_error("要添加到哪个字段的错误信息", ValidationError("提示的错误信息"))

验完成的最后都要将校验字典返回:return self.cleaned_data

在模板页面中,依然可以直接用所添加到字段的错误信息变量:form_obj.name.errors.0

示例:

def clean(self):pwd = self.cleaned_data.get("pwd")re_pwd = self.cleaned_data.get("re_pwd")if pwd != re_pwd:self.add_error("re_pwd", ValidationError("两次密码不一致!"))# raise ValidationError("两次密码不一致")return self.cleaned_data

Form 与数据库

有时候会遇到这样的需求:前端页面中,Form 表单里的数据是从数据库中取出来显示出来,此时如果向数据库中添加新的数据,前端页面不会显示出新添加的数据,只有在重启后端服务后才能重新从数据库中取出数据,便包含了新添加的数据。

解决方法:

在对 Form 类中要从数据库中取数据的字段来说,在该字段进行取数据,所以需要在每次实例化类的时候都重新对该字段进行赋值。

city = forms.ChoiceField(   choices=models.City.objects.all().values_list("id", "name"),label="所在城市",initial=1,widget=widgets.Select(attrs={"class": "form-control"})
)# 重写父类的初始化方法, 每次实例化类的时候都调用
def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)# 每次实例化类的时候都重新给choices赋值,保证更新数据库时数据同步更新self.fields["city"].widget.choices = models.City.objects.all().values_list("id", "name")

参考:https://www.cnblogs.com/liwenzhou/p/8747872.html

GitHub地址:https://github.com/protea-ban/oldboy/tree/master/s9day73/ajaxdemo

转载于:https://www.cnblogs.com/banshaohuan/p/9531807.html

Django的Form表单相关推荐

  1. django之Form表单

    HTML表单 在HTML中,表单是<form>...</form> 之间元素的集合,它们允许访问者输入文本.选择选项.操作对象和控制等等,然后将信息发送回服务器. 某些表单的元 ...

  2. 框架生成的HTML修改,Django框架form表单验证 修改html标签的样式

    经过前面的学习,我们大致可以知道CharField.EmailField等等以Field结尾的方法,只能帮助我们对用户发来的信息做验证,不能生成html标签.字段本身自己虽然只做验证,但是我们可以通过 ...

  3. Django(part46)--form表单验证

    学习笔记,仅供参考 文章目录 form表单验证 举个例子 form表单验证 form提供表单和字段验证,我们可以使用form.is_valid() 方法进行表单验证,若该方法返回值为True,则表示当 ...

  4. Django(part17)--form表单提交数据

    学习笔记,仅供参考,有错必纠 form表单 form表单的主要作用是和服务器进行交互,为服务器端提供数据. name属性 form表单有name属性,name属性类似于客户端与服务器端之间的约定. f ...

  5. Django之form表单组件、cookie与session

    ---恢复内容开始--- Form表单组件 引例: 先来看一个注册的例子,全部用的是reg函数来实现的. views.py文件 def reg(request):errors = {'username ...

  6. django,form表单,数据库增删改查

    Django 02  复习:   Django下载:    在命令行输入:     pip3 install django==1.11.11     在这里不要用最新的3.7,推荐使用3.6/3.5/ ...

  7. Django之Form表单验证组件Tyrion

    Tyrion是一个基于Python实现的支持多个WEB框架的Form表单验证组件,其完美的支持Tornado.Django.Flask.Bottle Web框架.Tyrion主要有两大重要动能: 表单 ...

  8. django ajax form表单,Django学习系列之Form表单和ajax(示例代码)

    昵       称: 生       日: 性       别:     男 女 地       址: 手  机  号: 邮       箱: [修改] {% csrf_token %}$(\'#js ...

  9. 在django的form表单及ajax提交的数据中添加认证的csrfmiddlewaretoken

    1. 对于ajax提交数据,把下面的代码加入到js的头部,可以保证ajax执行时自动提交参数csrfmiddlewaretoken. $.ajaxSetup({data: {csrfmiddlewar ...

最新文章

  1. Class com.googlecode.jsonplugin.JSONWriter ca...
  2. opencv_4.5.0/OpenCvSharp_已知目标物边界求重心
  3. linux排序语言,Linux sort 排序命令uniq去重复行
  4. 给页面字段中添加一个按钮,点击按钮实现弹窗效果
  5. PHP的array_column
  6. Using join buffer (Batched Key Access)
  7. 1003 我要通过! (20分)_26行代码AC
  8. android 遍历所有view,Android 算法:遍历ViewGroup找出所有子View
  9. 华为P50系列确定29日发布:但遗憾的是...
  10. (转)AI搅局金融业!传奇投资人“都铎·琼斯”真金白银来押注
  11. 梨花带雨音乐播放器3.91源码开源(网站添加背景音乐)
  12. PNP与NPN三极管开关特性
  13. 上海驾照科目三练习笔记
  14. 淘宝店铺店名起、分类如何定【太原网络营销师】教你
  15. 2019年西工大附中分校民办小升初电脑随机派位录取结果
  16. If I Have One Million
  17. 电力变电站三维可视化
  18. 计算机放音乐声音小在吗调,电脑放歌声音小怎么办
  19. 视频播放AVPlayer的使用
  20. 4.1.3 消费者轮询的流程

热门文章

  1. 再次发布SQL Prompt 3.8的新的patch,解决了不能格式化T-SQL的问题
  2. operate XML file (Open,Insert)
  3. 想知道深度学习卷积在GPU上如何优化吗?“大神”赵开勇带你深入浅出
  4. 训练MNIST数据集模型
  5. 《Neural networks and deep learning》概览
  6. DeepLearning tutorial(3)MLP多层感知机原理简介+代码详解
  7. 基于mysqld_multi实现MySQL 5.7.24多实例多进程配置
  8. linux nc 详解
  9. 使用IDEA搭建第一个SpringBoot程序
  10. linux 父子进程的关系