Django - form组件详解

文章目录

  • 1. Form组件的主要功能
  • 2. Form的处理流程
  • 3. Form常用字段
  • 4. Form常用的内置插件
    • 4.1 内置插件
    • 4.2 常用的插件
  • 5. 初始化页面显示
  • 6. 动态数据的更新
  • 7. 自定义验证规则
  • 8. ajax请求

1. Form组件的主要功能

  • HTML form提交数据后自动保留上次提交的数据
  • 对用户提交的数据进行验证并生成错误信息
  • 生成HTML标签
  • 初始化页面显示内容
  • 实时数据更新

2. Form的处理流程

  1. 在应用下面创建forms.py用来存放form组件的类
  2. 创建form类,类里面创建前端需要传入的字段
  3. 在views视图函数中进行对数据验证处理,成功进行跳转到新页面和失败返回到原来的页面。
  4. 模板HTML渲染页面

具体代码:
– 创建类:

from django import forms
from django.forms import fields
from django.forms import widgets


# 创建MyForms类
class MyForms(forms.Form):
    user = fields.CharField(   # 用户名
        max_length=18,
        min_length=6,
        required=True,
        error_messages = {
     
            "max_length": "用户名长度必须小于18位",
            "min_length": "用户名长度必须大于6位",
            "required": "用户名不能为空",
        })
    pwd = fields.CharField(  # 密码
        max_length=18,
        min_length=6,
        required=True,
        error_messages={
     
            "max_length": "密码长度必须小于18位",
            "min_length": "密码长度必须大于6位",
            "required": "密码不能为空",
        })
    gender = fields.ChoiceField(  # 性别
        choices=((1, '男'), (2, '女'),),
        initial=2,
        widget=widgets.RadioSelect
    )
    email = fields.EmailField(   # 邮箱
        required=True,
        error_messages={
     
            "Invalid": "邮箱格式有误",
            "required": "邮箱不能为空",
        })

– 视图函数:

from django.shortcuts import render, HttpResponse
from zhss.forms import MyForms

# 注册页面
def register(request):
    if request.method == "GET":
        obj = MyForms()
        return render(request, "zhss/register.html", context={
     "obj": obj})
    if request.method == "POST":
        obj = MyForms(request.POST)  # 提交数据都放在request.POST里面的
        if obj.is_valid(): # 进行数据验证
            return HttpResponse("验证成功")
        else:
            return render(request, "zhss/register.html", context={
     "obj": obj})

– 模板HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
    <form action="{% url "zhss:register" %}" method="post">
        {
     % csrf_token %}
        <p>用户名&emsp;{
     {
      obj.user }}{
     {
      obj.errors.user.0 }}</p>
        <p>用户密码&emsp;{
     {
      obj.pwd }}{
     {
      obj.errors.pwd.0 }}</p>
        <p>性别&emsp;{
     {
      obj.gender }}{
     {
      obj.errors.gender.0 }}</p>
        <p>邮箱&emsp;{
     {
      obj.email }}{
     {
      obj.errors.email.0 }}</p>
        <p><input type="submit" value="提交注册"></p>
    </form>
</body>
</html>

3. Form常用字段

本质上字段里面封装了一个正则表达式来匹配用户数据,同时还封装了HTML插件。

'''
在源码中,Field为BASE类,其他下面的字段都是继承BASE或者其他字段的。
'''
1.	Field中含有的参数:
	    required=True,               是否允许为空
	    widget=None,                 HTML插件
	    label=None,                  用于生成Label标签或显示内容
	    initial=None,                初始值
	    help_text='',                帮助信息(在标签旁边显示)
	    error_messages=None,         错误信息 {
     'required': '不能为空', 'invalid': '格式错误'}
	    show_hidden_initial=False,   是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
	    validators=[],               自定义验证规则
	    localize=False,              是否支持本地化
	    disabled=False,              是否可以编辑
	    label_suffix=None            Label内容后缀
 
2. RegexField(CharField)  # 自定义正则表达式字段
	    regex,                      自定制正则表达式
	    max_length=None,            最大长度
	    min_length=None,            最小长度
	    error_message=None,         忽略,错误信息使用 error_messages={
     'invalid': '...'}
 

3.	EmailField(CharField)      # 邮箱字段
    ...


4.	FileField(Field)# 文件字段
	    allow_empty_file=False     是否允许空文件
	     使用时需要注意两点:
	        - form表单中 enctype="multipart/form-data"
	        - view函数中 obj = MyForm(request.POST, request.FILES)


5.	ImageField(FileField)     # 图片字段 
    	...
	    注:需要PIL模块,pip3 install Pillow
	    使用时需要注意两点:
	        - form表单中 enctype="multipart/form-data"
	        - view函数中 obj = MyForm(request.POST, request.FILES) 
	        - 
6.	ChoiceField(Field)  # 选择字段
	    ...
	    choices=(),                选项,如:choices = ((0,'女'),(1,'男'),)
	    required=True,             是否必填
	    widget=None,               插件,默认select插件
	    label=None,                Label内容
	    initial=None,              初始值
	    help_text='',              帮助提示 
	    
7.	MultipleChoiceField(ChoiceField)	# 多选字段
    	...
      	        
8.	CharField(Field)# 字符串字段
	    max_length=None,             最大长度
	    min_length=None,             最小长度
	    strip=True                   是否移除用户输入空白


9.	IntegerField(Field)   # 整数字段
	    max_value=None,              最大值
	    min_value=None,              最小值
    

10.	FloatField(IntegerField)# 浮点数字段
    	...
 

11.	DecimalField(IntegerField)#  数值字段
	    max_value=None,              最大值
	    min_value=None,              最小值
	    max_digits=None,             总长度
	    decimal_places=None,         小数位长度
    
12. DateField(BaseTemporalField)    格式:2019-09-15  # 日期字段
13. TimeField(BaseTemporalField)    格式:15:12:11	# 时间字段
14. DateTimeField(BaseTemporalField)	格式:2019-09-15 11:12:13	# 日期时间字段
15. 
16. GenericIPAddressField    # ip地址字段
    protocol='both',           both,ipv4,ipv6支持的IP格式
    unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用

BaseTemporalField(Field) # 时间字段
    input_formats=None          时间格式化   

DurationField(Field)            时间间隔:%d %H:%M:%S.%f   # 时间间隔字段
    ...

URLField(Field)  # url字段
    ...

BooleanField(Field)  # 布尔值字段
    ...
   
NullBooleanField(BooleanField)  # 含有空值的布尔字段
    ...
 
ModelChoiceField(ChoiceField) #  数据库筛选字段
    ...                        django.forms.models.ModelChoiceField
    queryset,                  # 查询数据库中的数据
    empty_label="---------",   # 默认空显示内容
    to_field_name=None,        # HTML中value的值对应的字段
    limit_choices_to=None      # ModelForm中对queryset二次筛选
      
ModelMultipleChoiceField(ModelChoiceField)
    ...                        django.forms.models.ModelMultipleChoiceField
   
TypedChoiceField(ChoiceField)  # 类型转化字段
    coerce = lambda val: val   对选中的值进行一次转换
    empty_value= ''            空值的默认值
    
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=''
 
UUIDField(CharField)           uuid类型  # uuid字段
    ...

4. Form常用的内置插件

4.1 内置插件

内置插件都是搭配着widgets自定义HTML插件使用的因此需要导入模块widgets

1.	TextInput(Input)   					# 文本输入框
2.	NumberInput(TextInput)				# 数字文本输入框
3.	EmailInput(TextInput)				# 邮箱输入框
4.	URLInput(TextInput)					# url输入框
5.	PasswordInput(TextInput)			# 密码输入框
6.	HiddenInput(TextInput)				# 隐藏输入框
7.	Textarea(Widget)					# 多行文本输入框
8.	DateInput(DateTimeBaseInput)		# 日期输入框
9.	DateTimeInput(DateTimeBaseInput)	# 日期时间输入框
10.	TimeInput(DateTimeBaseInput)		# 时间输入框
11.	CheckboxInput						# 多选框
12.	Select								# 下拉框
13.	NullBooleanSelect					# 含空值的布尔下拉框
14.	SelectMultiple						# 多选下拉框
15.	RadioSelect							# 单选
16.	CheckboxSelectMultiple				# 多选
17.	FileInput							# 文件选择框

4.2 常用的插件

方法1:采用CharField

# 单选radio 方法1
    rad = fields.CharField(
        initial=1,
        widget=widgets.RadioSelect(choices=((0, '女'), (1, '男')))
    )
    
# 单选checkbox
    deal = fields.CharField(
        widget=widgets.CheckboxInput
    )
    
# 多选checkbox,值为列表 方法1
    ch_box = fields.CharField(
        initial=[1, 2, ],
        widget=widgets.CheckboxSelectMultiple(choices=((1, 'python'), (2, 'C++'), (3, 'C'), (4, 'JAVA')), )
    )
  
# 单选select下拉框 方法1
    sel = fields.CharField(
        initial=1,
        widget=widgets.Select(choices=((1, 'python'), (2, 'C++'), (3, 'C'), (4, 'JAVA')), )
    )
    
# 多选select下拉框 方法1
    mul_sel = fields.CharField(
        initial=[1, 2, ],
        widget=widgets.SelectMultiple(choices=((1, 'python'), (2, 'C++'), (3, 'C'), (4, 'JAVA')), )
    )
    

方法2:选用ChoiceField()


    # 单选radio 方法2
    rad = fields.ChoiceField(  # 性别
        choices=((0, '女'), (1, '男'),),
        initial=1,  # 默认为 女
        widget=widgets.RadioSelect  # 单选框
    )
    
    # 多选checkbox,值为列表 方法2
    ch_box = fields.MultipleChoiceField(
        choices=((1, 'python'), (2, 'C++'), (3, 'C'), (4, 'JAVA')),
        initial=[1, 2, ],
        widget=widgets.CheckboxSelectMultiple
    )

    # 单选select下拉框 方法2
    sel = fields.ChoiceField(
        choices=((1, 'python'), (2, 'C++'), (3, 'C'), (4, 'JAVA')),
        initial=1,
        widget=widgets.Select
    )

    # 多选select下拉框 方法2
    mul_sel = fields.MultipleChoiceField(
        choices=((1, 'python'), (2, 'C++'), (3, 'C'), (4, 'JAVA')),
        initial=[1, 2, ],
        widget=widgets.SelectMultiple
    )
 

5. 初始化页面显示

在很多是比如做数据的修改就需要将数据库初始化显示在模板渲染页面上:

– 在form创建的类中:

from django import forms
from django.forms import widgets
from django.forms import fields
 
 
class MyForm(forms.Form):
    type = fields.ChoiceField(
        choices=((1, 'python'), (2, 'C++'), (3, 'C'), (4, 'JAVA'),),
        widget=widgets.Select
    )

– 在views视图函数中:

from django.shortcuts import render, redirect
from django.http import HttpResponse
from zhss.forms import MyForms
 
 
def index(request):
    if request.method == "GET":
        values = {
      'type': 2}
        obj = MyForms(values)
        return render(request, 'zhss/index.html', context={
     'obj ': obj})
        
     if request.method == "POST":
        obj = MyForms(request.POST)  # 提交数据都放在request.POST里面的
        if obj.is_valid(): # 进行数据验证
            return HttpResponse("验证成功")
        else:
            return render(request, "zhss/index.html", context={
     "obj": obj})

– 在模板HTML中:

<form method="POST" action="{% url "zhss:index" %}" enctype="multipart/form-data">
    {
     % csrf_token %}
    <p>{
     {
      obj.type}} {
     {
      obj.obj.errors }}</p>
    <input type="submit" value="提交">
</form>

6. 动态数据的更新

from django import forms
from django.forms import widgets
from django.forms import fields
from zhss.models import ProLanguage
 
class MyForms(forms.Form):
    type = fields.ChoiceField(
        widget=widgets.Select(choiece=ProLanguage.objects.values_list('id','type'))
    )

当使用上面方式时,服务器运行时,MyForms类从上到下运行,type数据缓存在本地的,当数据库里面的数据进行更新时 ,从前端的下拉框中拿取的数据依然是数据库更新前的数据因为还是拿的缓存里面,如果想要拿到更新后的数据就必须想办法让类再运行一次即每次实例化对象时都运行一次。因此改进后的代码为:

from django import forms
from django.forms import widgets
from django.forms import fields
from zhss.models import ProLanguage
 
class MyForms(forms.Form):
    type = fields.ChoiceField(
        widget=widgets.Select()
    )
    def __init(self,*args,**kwargs):  # 每次实例化对象时都会调用一次__init__方法
    	super(MyForms,self).__init__(*args,**kwargs)
    	self.fields['type'].widget.choices = ProLanguage.objects.value_list('id','type')

7. 自定义验证规则

import re
from django import forms
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError
 
 
# 自定义验证规则
def phone_number(arg):
    phone_re = re.compile(r'^((13[0-9])|(17[0-1,6-8])|(15[^4,\\D])|(18[0-9]))\d{8}$')
    if not phone_re .match(arg):
        raise ValidationError('手机号码格式错误')
        
# form类       
class PublishForm(Form):
    # 使用自定义验证规则
    phone = fields.CharField(validators=[phone_number, ],
                            error_messages={
     'required': '手机不能为空'},
                            widget=widgets.TextInput(attrs={
     'placeholder': u'手机号码'}))

8. ajax请求

ajax请求处理时必须自己处理跳转,必须自己处理错误信息

–form类中

# ajax请求类
class AjaxForm(forms.Form):
    name = fields.CharField(max_length=32, min_length=6, required=True)
    type = fields.ChoiceField(
        choices=((0, "张三"), (1, "李四"), (2, "王五"),),
        widget=widgets.Select
    )

    def __init(self, *args, **kwargs):  # 每次实例化对象时都会调用一次__init__方法
        super(AjaxForm, self).__init__(*args, **kwargs)
        self.fields['type'].widget.choices = Classes.objects.value_list('id', 'type')

–views视图函数中

def ajax(request):
    if request.method == "GET":
        obj = AjaxForm()
        return render(request, "zhss/ajax.html", context={
     "obj": obj})
    if request.method == "POST":
        res = {
     "status": False, "message": None}
        obj = AjaxForm(request.POST)
        if obj.is_valid():
            #print(obj.cleaned_data)
            res["status"] = True
            return HttpResponse(json.dumps(res))
        else:
            res["message"] = obj.errors  # errors里面有as_ul(默认),as_json,as_data,as_text
            return HttpResponse(json.dumps(res))

–模板渲染HTML中:

<form id="fm" action="{% url 'zhss:ajax' %}"  method="post">
    {
     % csrf_token %}
    <p>名字:{
     {
      obj.name }}<span id="name"></span></p>
    <p>类型:{
     {
      obj.type }}<span id="type"></span></p>
    <p><input type="button" value="提交" id="btn"></p>  {
     # 这里需要使用button 不能用submit #}

</form>
<script src="{% static 'jQuery_3.3.1.js' %}"></script>
<script>
    $(function () {
     
        $("#btn").click(function () {
     
            $.ajax({
     
                url:"{% url "zhss:ajax" %}",
                type: "POST",
                data:$("#fm").serialize(), {
     # 获取到当前form表单里面的所有数据 #}
                dataType:"JSON",
                success:function (arg) {
     
                    # console.log(arg);
                    if(arg.status == true){
        {
     # 状态为真则跳转到指定页面,这里的true不能加引号 #}
                        window.location.href="{% url "zhss:register" %}";
                     }else{
     
                     	# console.log(arg.message.name[0]);
                        $("#name").html(arg.message.name[0]) {
     # 显示错误信息 #}
                     }
                }
            })
        })
    })
</script>

你可能感兴趣的:(Django,Form组件)