Django-form表单

Posted 无名!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django-form表单相关的知识,希望对你有一定的参考价值。

在Django 中构建一个表单

使用form组件的优点:
1.form表单提交数据时,数据出现错误,返回的页面中仍可以保存之前输入的数据。
2.自定义限制字段的条件。

from类

技术分享图片
from django import forms

# 改变input框类型type
from django.forms import widgets
class Loginform(forms.Form):
    user = forms.CharField(max_length=12, min_length=3,
                           error_messages={
                               "required": "不能为空",  # 设置提示错误信息
                               "max_length": "最大长度不能超过6",
                               "min_length": "最小长度不能小于3",
                           }
                           )

    phone = forms.CharField(
        error_messages={
            "required": "不能为空",
        }
    )

    email = forms.EmailField(error_messages={
        "required": "不能为空",
        "invalid": "格式错误"}
    )

    pwd = forms.CharField(max_length=8, min_length=4,
                          error_messages={
                              "required": "不能为空",
                              "max_length": "最大长度不能超过8",
                              "min_length": "最小长度不能小于4",
                          },
                          widget=widgets.PasswordInput(attrs={"class": "active"})  # attrs自定义类属性
                          )

    rpwd = forms.CharField(max_length=8, min_length=4,
                           error_messages={
                               "required": "不能为空",
                               "max_length": "最大长度不能超过8",
                               "min_length": "最小长度不能小于4",
                           },
                           widget=widgets.PasswordInput()
                           )
form类

定义一个Form 类,任意写字段。

字段允许的最大长度通过max_length 定义。它完成两件事情。首先,它在html<input> 上放置一个maxlength="100"(这样浏览器将在第一时间阻止用户输入多于这个数目的字符)。它还意味着当Django 收到浏览器发送过来的表单时,它将验证数据的长度。

Form 的实例具有一个is_valid() 方法,它为所有的字段运行验证的程序。当调用这个方法时,如果所有的字段都包含合法的数据,它将:

  • 返回True
  • 将表单的数据放到cleaned_data属性中。

完整的表单,第一次渲染时,看上去将像:

1
2
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" maxlength="100">

 注意它不包含 <form> 标签和提交按钮。我们必须自己在模板中提供它们。

视图

技术分享图片
def login(request):
    if request.method == "POST":
        print(request.POST)
        form_obj = Loginform(request.POST)

        if form_obj.is_valid():  # 是否校验成功返回bool  is_vaild()方法是父类(Form)的
            # 1.数据全部合格
            # 2.取出合格数据


            print(form_obj.cleaned_data)  # 放合格数据
            name = form_obj.cleaned_data
            del name["rpwd"]
            phone =form_obj.cleaned_data.get("phone")
            # # 增加到数据库
            print(name)
            models.User_info.objects.create(**name)

            return redirect("/index/")
        else:
            # 1.至少存在一个错误字段
            # 2.取出合格数据

            # print(form_obj.errors)  # 存放错误信息,错误信息可以多条  {"字段":["","",""]}
            # print(type(form_obj.errors))  # class ‘django.forms.utils.ErrorDict‘>
            #
            # print(form_obj.errors["user"])  # 找到user字段的错误信息
            # print(type(form_obj.errors["user"]))  # <class ‘django.forms.utils.ErrorList‘>
            print("*" * 120)
            print(form_obj.errors)  # 全局钩子错误信息
            print(type(form_obj.errors))
            print(form_obj.errors.get("__all__"))  # 取出全局钩子错误信息

            all_errors = form_obj.errors.get("__all__")
            return render(request, "login.html", {"form_obj": form_obj, "all_errors": all_errors})

    form_obj = Loginform()  # 实例化对象 没有传值
    return render(request, "login.html", {"form_obj": form_obj})
视图

如果访问视图的是一个GET 请求,它将创建一个空的表单实例并将它放置到要渲染的模板的上下文中。这是我们在第一个访问该URL 时预期发生的情况。

如果表单的提交使用POST 请求,那么视图将再次创建一个表单实例并使用请求中的数据填充它:form = NameForm(request.POST)。这叫做”绑定数据至表单“(它现在是一个绑定的表单)。

我们调用表单的is_valid()方法;如果它不为True,我们将带着这个表单返回到模板。这时表单不再为空(未绑定),所以HTML 表单将用之前提交的数据填充,然后可以根据要求编辑并改正它。

如果is_valid()True,我们将能够在cleaned_data 属性中找到所有合法的表单数据。在发送HTTP 重定向给浏览器告诉它下一步的去向之前,我们可以用这个数据来更新数据库或者做其它处理。

模板(三种方法)

技术分享图片
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 6     <meta name="viewport" content="width=device-width, initial-scale=1">
 7     <title>Title</title>
 8 
 9 </head>
10 <body>
11 
12 ################方法一#################
13 #只产生<p>和<input>,一般不建议使用
14 <form action="" method="post">
15     {% csrf_token %}
16    {{ form_obj.as_p }}
17    <input type="submit">
18 </form>
19 ################方法二#################
20 #自定义标签类型
21 <form action="" novalidate method="post">
22     {% csrf_token %}
23     <h3>注册用户</h3>
24     <div><label for="">用户姓名</label>
25         {{ form_obj.user }} <span>{{ form_obj.errors.user.0 }}</span>    {# 输入框    错误信息 #}
26     </div>
27 
28     <div><label for="">联系方式</label>
29         {{ form_obj.phone }} <span>{{ form_obj.errors.phone.0 }}</span>
30     </div>
31 
32     <div><label for="">个人邮箱 </label>
33         {{ form_obj.email }} <span>{{ form_obj.errors.email.0 }}</span>
34     </div>
35 
36     <div><label for="">用户密码</label>
37         {{ form_obj.pwd }} <span>{{ form_obj.errors.pwd.0 }}</span>
38     </div>
39 
40     <div><label for="">确认密码</label>
41 {#        {{ form_obj.rpwd }} <span>{{  form_obj.errors.repwd.0 }}{{ form_obj.non_field_errors.0 }}</span>#}
42         {{ form_obj.rpwd }} <span>{{  form_obj.errors.repwd.0 }}{{ all_errors.0 }}</span>
43     </div>
44 
45     <input type="submit" value="注册">
46 
47 </form>
48 ###############方法三#################
49 #field.label 得到字段名字
50 <form action="" novalidate method="post">
51     {% csrf_token %}
52     {% for field in form_obj %}    
53        </div>                                                                                                       
54             <label for="">{{ field.label }}</label>                                               
55            {{ field }}    
56         </div>                                           
57                                         
58         {% endfor %}
59 <input type="submit">
60 </form>
61 
62 </body>
63 </html> 
三种方法

Django Form 类详解

绑定的和未绑定的表单实例

绑定的和未绑定的表单 之间的区别非常重要:

  • 未绑定的表单没有关联的数据。当渲染给用户时,它将为空或包含默认的值。
  • 绑定的表单具有提交的数据,因此可以用来检验数据是否合法。如果渲染一个不合法的绑定的表单,它将包含内联的错误信息,告诉用户如何纠正数据。

Widgets

每个表单字段都有一个对应的Widget 类,它对应一个HTML 表单Widget,例如<input type="text">

在大部分情况下,字段都具有一个合理的默认Widget。例如,默认情况下,CharField 具有一个TextInput Widget,它在HTML 中生成一个<input type="text">

字段的数据

不管表单提交的是什么数据,一旦通过调用is_valid() 成功验证(is_valid() 返回True),验证后的表单数据将位于form.cleaned_data 字典中。这些数据已经为你转换好为Python 的类型。

注:此时,你依然可以从request.POST 中直接访问到未验证的数据,但是访问验证后的数据更好一些。

在上面的联系表单示例中,is_married将是一个布尔值。类似地,IntegerField 和FloatField 字段分别将值转换为Python 的int 和float

 form组件的钩子

技术分享图片
    # 自定义校验规则
    # 局部钩子
    def clean_user(self):
        user = self.cleaned_data.get("user")
        # 校验用户输入user和数据库user
        name = models.User_info.objects.filter(user=user)
        if not name:
            return user
        else:
            raise ValidationError("用户名已注册")

    def clean_phone(self):
        phone=self.cleaned_data.get("phone")
        ret=re.search("^1[3578]\d{9}$",phone)
        if ret:
            return phone
        else:
            raise ValidationError("手机格式不正确")


    # 全局钩子 先校验字段条件和局部钩子条件(到这一步数据全部合格)
    def clean(self):
        pwd = self.cleaned_data.get("pwd")
        rpwd = self.cleaned_data.get("rpwd")
        if pwd == rpwd:
            return self.cleaned_data
        else:
            raise ValidationError("两次密码不一致")
View Code

form组件补充

1.Django内置字段如下:

技术分享图片
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内容后缀
 
 
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:12
 
DurationField(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.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= ‘‘            空值的默认值
 
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=‘‘
 
GenericIPAddressField
    protocol=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内置字段

2、常用选择插件:

技术分享图片
 1 # 单radio,值为字符串
 2 # user = fields.CharField(
 3 #     initial=2,
 4 #     widget=widgets.Radioselect(choices=((1,‘上海‘),(2,‘北京‘),))
 5 # )
 6  
 7 # 单radio,值为字符串
 8 # user = fields.ChoiceField(
 9 #     choices=((1, ‘上海‘), (2, ‘北京‘),),
10 #     initial=2,
11 #     widget=widgets.RadioSelect
12 # )
13  
14 # 单select,值为字符串
15 # user = fields.CharField(
16 #     initial=2,
17 #     widget=widgets.Select(choices=((1,‘上海‘),(2,‘北京‘),))
18 # )
19  
20 # 单select,值为字符串
21 # user = fields.ChoiceField(
22 #     choices=((1, ‘上海‘), (2, ‘北京‘),),
23 #     initial=2,
24 #     widget=widgets.Select
25 # )
26  
27 # 多选select,值为列表
28 # user = fields.MultipleChoiceField(
29 #     choices=((1,‘上海‘),(2,‘北京‘),),
30 #     initial=[1,],
31 #     widget=widgets.SelectMultiple
32 # )
33  
34  
35 # 单checkbox
36 # user = fields.CharField(
37 #     widget=widgets.CheckboxInput()
38 # )
39  
40  
41 # 多选checkbox,值为列表
42 # user = fields.MultipleChoiceField(
43 #     initial=[2, ],
44 #     choices=((1, ‘上海‘), (2, ‘北京‘),),
45 #     widget=widgets.CheckboxSelectMultiple
46 # )
模板插件

 

以上是关于Django-form表单的主要内容,如果未能解决你的问题,请参考以下文章

Django-form表单

10.Django-form表单

Django-form表单

Django-form表单

Django-form表单

Django-Form表单(验证定制错误信息Select)