首页 > 代码库 > 框架----Django之Form组件

框架----Django之Form组件

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

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

一、小试牛刀

1、创建Form类

技术分享
 1 from django.forms import Form 2 from django.forms import widgets 3 from django.forms import fields 4   5 class MyForm(Form): 6     user = fields.CharField( 7         widget=widgets.TextInput(attrs={id: i1, class: c1}) 8     ) 9  10     gender = fields.ChoiceField(11         choices=((1, ), (2, ),),12         initial=2,13         widget=widgets.RadioSelect14     )15  16     city = fields.CharField(17         initial=2,18         widget=widgets.Select(choices=((1,上海),(2,北京),))19     )20  21     pwd = fields.CharField(22         widget=widgets.PasswordInput(attrs={class: c1}, render_value=http://www.mamicode.com/True)23     )
View Code

2、View函数处理

技术分享
 1 from django.shortcuts import render, redirect 2 from .forms import MyForm 3   4   5 def index(request): 6     if request.method == "GET": 7         obj = MyForm() 8         return render(request, index.html, {form: obj}) 9     elif request.method == "POST":10         obj = MyForm(request.POST, request.FILES)11         if obj.is_valid():12             values = obj.clean()13             print(values)14         else:15             errors = obj.errors16             print(errors)17         return render(request, index.html, {form: obj})18     else:19         return redirect(http://www.google.com)
View Code

3、生成HTML

技术分享
1 <form action="/" method="POST" enctype="multipart/form-data">2     <p>{{ form.user }} {{ form.user.errors }}</p>3     <p>{{ form.gender }} {{ form.gender.errors }}</p>4     <p>{{ form.city }} {{ form.city.errors }}</p>5     <p>{{ form.pwd }} {{ form.pwd.errors }}</p>6     <input type="submit"/>7 </form>
View Code
技术分享
 1 <form method="POST" enctype="multipart/form-data"> 2         {% csrf_token %} 3          4             {{ form.xxoo.label }} 5             {{ form.xxoo.id_for_label }} 6             {{ form.xxoo.label_tag }} 7             {{ form.xxoo.errors }} 8             <p>{{ form.user }} {{ form.user.errors }}</p> 9             <input type="submit" />10     </form>11 12 其他标签有
其他标签有

二、Form类

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

1、Django内置字段如下:

技术分享
  1 Field  2     required=True,               是否允许为空  3     widget=None,                 HTML插件  4     label=None,                  用于生成Label标签或显示内容  5     initial=None,                初始值  6     help_text=‘‘,                帮助信息(在标签旁边显示)  7     error_messages=None,         错误信息 {required: 不能为空, invalid: 格式错误}  8     show_hidden_initial=False,   是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)  9     validators=[],               自定义验证规则 10     localize=False,              是否支持本地化 11     disabled=False,              是否可以编辑 12     label_suffix=None            Label内容后缀 13   14   15 CharField(Field) 16     max_length=None,             最大长度 17     min_length=None,             最小长度 18     strip=True                   是否移除用户输入空白 19   20 IntegerField(Field) 21     max_value=http://www.mamicode.com/None,              最大值 22     min_value=http://www.mamicode.com/None,              最小值 23   24 FloatField(IntegerField) 25     ... 26   27 DecimalField(IntegerField) 28     max_value=http://www.mamicode.com/None,              最大值 29     min_value=http://www.mamicode.com/None,              最小值 30     max_digits=None,             总长度 31     decimal_places=None,         小数位长度 32   33 BaseTemporalField(Field) 34     input_formats=None          时间格式化    35   36 DateField(BaseTemporalField)    格式:2015-09-01 37 TimeField(BaseTemporalField)    格式:11:12 38 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12 39   40 DurationField(Field)            时间间隔:%d %H:%M:%S.%f 41     ... 42   43 RegexField(CharField) 44     regex,                      自定制正则表达式 45     max_length=None,            最大长度 46     min_length=None,            最小长度 47     error_message=None,         忽略,错误信息使用 error_messages={invalid: ...} 48   49 EmailField(CharField)       50     ... 51   52 FileField(Field) 53     allow_empty_file=False     是否允许空文件 54   55 ImageField(FileField)       56     ... 57     注:需要PIL模块,pip3 install Pillow 58     以上两个字典使用时,需要注意两点: 59         - form表单中 enctype="multipart/form-data" 60         - view函数中 obj = MyForm(request.POST, request.FILES) 61   62 URLField(Field) 63     ... 64   65   66 BooleanField(Field)   67     ... 68   69 NullBooleanField(BooleanField) 70     ... 71   72 ChoiceField(Field) 73     ... 74     choices=(),                选项,如:choices = ((0,上海),(1,北京),) 75     required=True,             是否必填 76     widget=None,               插件,默认select插件 77     label=None,                Label内容 78     initial=None,              初始值 79     help_text=‘‘,              帮助提示 80   81   82 ModelChoiceField(ChoiceField) 83     ...                        django.forms.models.ModelChoiceField 84     queryset,                  # 查询数据库中的数据 85     empty_label="---------",   # 默认空显示内容 86     to_field_name=None,        # HTML中value的值对应的字段 87     limit_choices_to=None      # ModelForm中对queryset二次筛选 88       89 ModelMultipleChoiceField(ModelChoiceField) 90     ...                        django.forms.models.ModelMultipleChoiceField 91   92   93       94 TypedChoiceField(ChoiceField) 95     coerce = lambda val: val   对选中的值进行一次转换 96     empty_value= http://www.mamicode.com/‘‘            空值的默认值 97   98 MultipleChoiceField(ChoiceField) 99     ...100  101 TypedMultipleChoiceField(MultipleChoiceField)102     coerce = lambda val: val   对选中的每一个值进行一次转换103     empty_value= http://www.mamicode.com/‘‘            空值的默认值104  105 ComboField(Field)106     fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式107                                fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])108  109 MultiValueField(Field)110     PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用111  112 SplitDateTimeField(MultiValueField)113     input_date_formats=None,   格式列表:[%Y--%m--%d, %m%d/%Y, %m/%d/%y]114     input_time_formats=None    格式列表:[%H:%M:%S, %H:%M:%S.%f, %H:%M]115  116 FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中117     path,                      文件夹路径118     match=None,                正则匹配119     recursive=False,           递归下面的文件夹120     allow_files=True,          允许文件121     allow_folders=False,       允许文件夹122     required=True,123     widget=None,124     label=None,125     initial=None,126     help_text=‘‘127  128 GenericIPAddressField129     protocol=both,           both,ipv4,ipv6支持的IP格式130     unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用131  132 SlugField(CharField)           数字,字母,下划线,减号(连字符)133     ...134  135 UUIDField(CharField)           uuid类型136     ...
View Code

注:UUID是根据MAC以及当前时间等创建的不重复的随机字符串

技术分享
 1 >>> import uuid 2  3     # make a UUID based on the host ID and current time 4     >>> uuid.uuid1()    # doctest: +SKIP 5     UUID(a8098c1a-f86e-11da-bd1a-00112444be1e) 6  7     # make a UUID using an MD5 hash of a namespace UUID and a name 8     >>> uuid.uuid3(uuid.NAMESPACE_DNS, python.org) 9     UUID(6fa459ea-ee8a-3ca4-894e-db77e160355e)10 11     # make a random UUID12     >>> uuid.uuid4()    # doctest: +SKIP13     UUID(16fd2706-8baf-433b-82eb-8c7fada847da)14 15     # make a UUID using a SHA-1 hash of a namespace UUID and a name16     >>> uuid.uuid5(uuid.NAMESPACE_DNS, python.org)17     UUID(886313e1-3b8a-5372-9b90-0c9aee199e5d)18 19     # make a UUID from a string of hex digits (braces and hyphens ignored)20     >>> x = uuid.UUID({00010203-0405-0607-0809-0a0b0c0d0e0f})21 22     # convert a UUID to a string of hex digits in standard form23     >>> str(x)24     00010203-0405-0607-0809-0a0b0c0d0e0f25 26     # get the raw 16 bytes of the UUID27     >>> x.bytes28     b\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f29 30     # make a UUID from a 16-byte string31     >>> uuid.UUID(bytes=x.bytes)32     UUID(00010203-0405-0607-0809-0a0b0c0d0e0f)
View Code

2、Django内置插件:

技术分享
TextInput(Input)NumberInput(TextInput)EmailInput(TextInput)URLInput(TextInput)PasswordInput(TextInput)HiddenInput(TextInput)Textarea(Widget)DateInput(DateTimeBaseInput)DateTimeInput(DateTimeBaseInput)TimeInput(DateTimeBaseInput)CheckboxInputSelectNullBooleanSelectSelectMultipleRadioSelectCheckboxSelectMultipleFileInputClearableFileInputMultipleHiddenInputSplitDateTimeWidgetSplitHiddenDateTimeWidgetSelectDateWidget
View Code

三、常用选择插件

技术分享
 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.RadioSelect12 # )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.Select25 # )26  27 # 多选select,值为列表28 # user = fields.MultipleChoiceField(29 #     choices=((1,‘上海‘),(2,‘北京‘),),30 #     initial=[1,],31 #     widget=widgets.SelectMultiple32 # )33  34  35 # 单checkbox36 # 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.CheckboxSelectMultiple46 # )
View Code

在使用选择标签时,需要注意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)
View Code

方式二:

使用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())
View Code

四、自定义验证规则

方式一:

技术分享
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     )
View Code

方式二:

技术分享
 1 import re 2 from django.forms import Form 3 from django.forms import widgets 4 from django.forms import fields 5 from django.core.exceptions import ValidationError 6   7   8 # 自定义验证规则 9 def mobile_validate(value):10     mobile_re = re.compile(r^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$)11     if not mobile_re.match(value):12         raise ValidationError(手机号码格式错误)13  14  15 class PublishForm(Form):16  17  18     title = fields.CharField(max_length=20,19                             min_length=5,20                             error_messages={required: 标题不能为空,21                                             min_length: 标题最少为5个字符,22                                             max_length: 标题最多为20个字符},23                             widget=widgets.TextInput(attrs={class: "form-control",24                                                           placeholder: 标题5-20个字符}))25  26  27     # 使用自定义验证规则28     phone = fields.CharField(validators=[mobile_validate, ],29                             error_messages={required: 手机不能为空},30                             widget=widgets.TextInput(attrs={class: "form-control",31                                                           placeholder: u手机号码}))32  33     email = fields.EmailField(required=False,34                             error_messages={required: u邮箱不能为空,invalid: u邮箱格式错误},35                             widget=widgets.TextInput(attrs={class: "form-control", placeholder: u邮箱}))
View Code

方法三:自定义方法

技术分享
 1 from django import forms 2     from django.forms import fields 3     from django.forms import widgets 4     from django.core.exceptions import ValidationError 5     from django.core.validators import RegexValidator 6   7     class FInfo(forms.Form): 8         username = fields.CharField(max_length=5, 9                                     validators=[RegexValidator(r^[0-9]+$, Enter a valid extension., invalid)], )10         email = fields.EmailField()11  12         def clean_username(self):13             """14             Form中字段中定义的格式匹配完之后,执行此方法进行验证15             :return:16             """17             value = http://www.mamicode.com/self.cleaned_data[username]18             if "666" in value:19                 raise ValidationError(666已经被玩烂了..., invalid)20             return value
View Code

方式四:同时生成多个标签进行验证

技术分享
 1 from django.forms import Form 2 from django.forms import widgets 3 from django.forms import fields 4   5 from django.core.validators import RegexValidator 6   7   8 ############## 自定义字段 ############## 9 class PhoneField(fields.MultiValueField):10     def __init__(self, *args, **kwargs):11         # Define one message for all fields.12         error_messages = {13             incomplete: Enter a country calling code and a phone number.,14         }15         # Or define a different message for each field.16         f = (17             fields.CharField(18                 error_messages={incomplete: Enter a country calling code.},19                 validators=[20                     RegexValidator(r^[0-9]+$, Enter a valid country calling code.),21                 ],22             ),23             fields.CharField(24                 error_messages={incomplete: Enter a phone number.},25                 validators=[RegexValidator(r^[0-9]+$, Enter a valid phone number.)],26             ),27             fields.CharField(28                 validators=[RegexValidator(r^[0-9]+$, Enter a valid extension.)],29                 required=False,30             ),31         )32         super(PhoneField, self).__init__(error_messages=error_messages, fields=f, require_all_fields=False, *args,33                                          **kwargs)34  35     def compress(self, data_list):36         """37         当用户验证都通过后,该值返回给用户38         :param data_list:39         :return:40         """41         return data_list42  43 ############## 自定义插件 ##############44 class SplitPhoneWidget(widgets.MultiWidget):45     def __init__(self):46         ws = (47             widgets.TextInput(),48             widgets.TextInput(),49             widgets.TextInput(),50         )51         super(SplitPhoneWidget, self).__init__(ws)52  53     def decompress(self, value):54         """55         处理初始值,当初始值initial不是列表时,调用该方法56         :param value:57         :return:58         """59         if value:60             return value.split(,)61         return [None, None, None]
View Code

五、初始化数据

在Web应用程序中开发编写功能时,时常用到获取数据库中的数据并将值初始化在HTML中的标签上。

1、Form

技术分享
 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   7 class MyForm(Form): 8     user = fields.CharField() 9  10     city = fields.ChoiceField(11         choices=((1, 上海), (2, 北京),),12         widget=widgets.Select13     )
View Code

2、Views

技术分享
 1 from django.shortcuts import render, redirect 2 from .forms import MyForm 3   4   5 def index(request): 6     if request.method == "GET": 7         values = {user: root, city: 2} 8         obj = MyForm(values) 9  10         return render(request, index.html, {form: obj})11     elif request.method == "POST":12         return redirect(http://www.google.com)13     else:14         return redirect(http://www.google.com)
View Code

3、HTML

技术分享
1 <form method="POST" enctype="multipart/form-data">2     {% csrf_token %}3     <p>{{ form.user }} {{ form.user.errors }}</p>4     <p>{{ form.city }} {{ form.city.errors }}</p>5  6     <input type="submit"/>7 </form>
View Code

 

框架----Django之Form组件