Django之Form组件

来源:互联网 发布:申通淘宝面单打印软件 编辑:程序博客网 时间:2024/06/07 00:14

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

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

利用Form实现用户认证

一、创建Form类

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsclass PublishForm(forms.Form):    username = fields.CharField(error_messages={'required':'用户名不能为空'},                                widget=widgets.TextInput(attrs={'class':'c1'}),                                label='用户名:')     #label用于生成Label标签或显示内容    pwd = fields.CharField(min_length=6,error_messages={'required':'密码不能为空','min_length':'密码最小为6位'},                           widget=widgets.PasswordInput)    email = fields.EmailField(error_messages={'required':'邮箱不能为空','invalied':'邮箱格式不正确'},                              widget=widgets.EmailInput(attrs={'class':'c2'}))    f = fields.FileField(allow_empty_file=False)    #文件

备注:
widget就是帮我们给标签添加样式用的,例如我们给username标签添加了一个属性class=’c1’,后面我们直接定义c1的样式即可,也可以添加多个。

二、View函数处理

from django.shortcuts import renderfrom app01.form import PublishFormdef login(request):    if request.method == 'GET':        obj = PublishForm()        #return render(request,'login.html')   #方式一        return render(request,'login.html',{'obj':obj})  #方式二    elif request.method == 'POST':        obj = PublishForm(request.POST)    #将所有的POST请求进行验证          val = obj.is_valid()               #有一个返回值,填写格式都正确为True,否则为False        if val :            print(obj.cleaned_data)        #将用户输入的信息以字典形式展现,这样我们就可以直接写入到数据库中**obj.cleaned_data        else:            print(obj.errors)              #所有错误信息            print(obj.errors.as_json())    #错误信息,json字典格式            return  render(request,'login.html',{'obj':obj})            

三、生成HTML

方式一:<form method="post" action="/login/">    <p>用户名:<input type="text" name="username" /> {{ obj.errors.username.0 }}</p>    <p>密码:<input type="password" name="pwd" /> {{ obj.errors.pwd.0 }}</p>    <p>邮箱:<input type="text" name="email" />  {{ obj.errors.email.0 }}</p>    <p><input type="file" name="f" /></p>    <p><input type="submit" name="提交" /></p>    {% csrf_token %}</form>方式二:<form method="post" action="/login/">    <p>{{ obj.username.label }}{{ obj.username }} {{ obj.errors.username.0 }}</p>    <p>密码:{{ obj.pwd }} {{ obj.errors.pwd.0 }}</p>    <p>邮箱:{{ obj.email }}  {{ obj.errors.email.0 }}</p>    <p>{{ obj.f }}  {{ obj.errors.f.0 }}</p>    <p><input type="submit" name="提交" /></p>    {% csrf_token %}</form>

备注:
建议用第二种方式生产form表单里面的内容,这样会保留里面的数据。{{ obj.username.label }} 是自动生成用户名的,由于在前面已经定义了。

四、其他标签

<form method="POST" enctype="multipart/form-data">    {% csrf_token %}           {{ obj.xxoo.label }}        {{ obj.xxoo.id_for_label }}        {{ obj.xxoo.label_tag }}        {{ obj.xxoo.errors }}        <p>{{ obj.username }} {{ obj.username.errors }}</p>        <input type="submit" /></form>#xxoo为列中的字段名

备注:以下是在Form里面自动生成标签,有下面三种方式

<form method="POST" enctype="multipart/form-data">    {% csrf_token %}           ①p标签方式显示  {{ obj.as_p }}        ②ul方式显示  {{ obj.as_ul }}        ③表格方式显示        <table>            {{ obj.as_table}}        <table/></form>

Form类

创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;
一、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-01TimeField(BaseTemporalField)        格式:11:12DateTimeField(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.ModelChoiceField    queryset,                   # 查询数据库中的数据    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=''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类型    ...

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

>>> import uuid    # make a UUID based on the host ID and current time    >>> uuid.uuid1()    # doctest: +SKIP    UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')    # make a UUID using an MD5 hash of a namespace UUID and a name    >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')    UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')    # make a random UUID    >>> uuid.uuid4()    # doctest: +SKIP    UUID('16fd2706-8baf-433b-82eb-8c7fada847da')    # make a UUID using a SHA-1 hash of a namespace UUID and a name    >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')    UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')    # make a UUID from a string of hex digits (braces and hyphens ignored)    >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')    # convert a UUID to a string of hex digits in standard form    >>> str(x)    '00010203-0405-0607-0809-0a0b0c0d0e0f'    # get the raw 16 bytes of the UUID    >>> x.bytes    b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'    # make a UUID from a 16-byte string    >>> uuid.UUID(bytes=x.bytes)    UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')

二、Django内置插件

TextInput(Input)NumberInput(TextInput)EmailInput(TextInput)URLInput(TextInput)PasswordInput(TextInput)HiddenInput(TextInput)Textarea(Widget)DateInput(DateTimeBaseInput)DateTimeInput(DateTimeBaseInput)TimeInput(DateTimeBaseInput)CheckboxInputSelectNullBooleanSelectSelectMultipleRadioSelectCheckboxSelectMultipleFileInputClearableFileInputMultipleHiddenInputSplitDateTimeWidgetSplitHiddenDateTimeWidgetSelectDateWidget

三、常用选择插件

# 单radio,值为字符串# user = fields.CharField(#     initial=2,#     widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))# )# 单radio,值为字符串# user = fields.ChoiceField(#     choices=((1, '上海'), (2, '北京'),),#     initial=2,#     widget=widgets.RadioSelect# )# 单select,值为字符串# user = fields.CharField(#     initial=2,#     widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))# )# 单select,值为字符串# user = fields.ChoiceField(#     choices=((1, '上海'), (2, '北京'),),#     initial=2,#     widget=widgets.Select# )# 多选select,值为列表# user = fields.MultipleChoiceField(#     choices=((1,'上海'),(2,'北京'),),#     initial=[1,],#     widget=widgets.SelectMultiple# )# 单checkbox# user = fields.CharField(#     widget=widgets.CheckboxInput()# )# 多选checkbox,值为列表# user = fields.MultipleChoiceField(#     initial=[2, ],#     choices=((1, '上海'), (2, '北京'),),#     widget=widgets.CheckboxSelectMultiple# )



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

方式一:

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsfrom django.core.validators import RegexValidatorclass MyForm(Form):    user = fields.ChoiceField(        # choices=((1, '上海'), (2, '北京'),),        initial=2,        widget=widgets.Select    )    def __init__(self, *args, **kwargs):        super(MyForm,self).__init__(*args, **kwargs)        # self.fields['user'].widget.choices = ((1, '上海'), (2, '北京'),)        # 或        self.fields['user'].widget.choices = models.Classes.objects.all().value_list('id','caption')

方式二:
使用django提供的ModelChoiceField和ModelMultipleChoiceField字段来实现

from django import formsfrom django.forms import fieldsfrom django.forms import widgetsfrom django.forms import models as form_modelfrom django.core.exceptions import ValidationErrorfrom django.core.validators import RegexValidatorclass FInfo(forms.Form):    authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())    # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())

自定义验证规则

方式一:

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsfrom django.core.validators import RegexValidatorclass MyForm(Form):    user = fields.CharField(        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],    )

方式二:

import refrom django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsfrom django.core.exceptions import ValidationError# 自定义验证规则def mobile_validate(value):    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')    if not mobile_re.match(value):        raise ValidationError('手机号码格式错误')class PublishForm(Form):    title = fields.CharField(max_length=20,                            min_length=5,                            error_messages={'required': '标题不能为空',                                            'min_length': '标题最少为5个字符',                                            'max_length': '标题最多为20个字符'},                            widget=widgets.TextInput(attrs={'class': "form-control",                                                          'placeholder': '标题5-20个字符'}))    # 使用自定义验证规则    phone = fields.CharField(validators=[mobile_validate, ],                            error_messages={'required': '手机不能为空'},                            widget=widgets.TextInput(attrs={'class': "form-control",                                                          'placeholder': u'手机号码'}))    email = fields.EmailField(required=False,                            error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},                            widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))

方法三:自定义方法

from django import forms    from django.forms import fields    from django.forms import widgets    from django.core.exceptions import ValidationError    from django.core.validators import RegexValidator    class FInfo(forms.Form):        username = fields.CharField(max_length=5,                                    validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.', 'invalid')], )        email = fields.EmailField()        def clean_username(self):            """            Form中字段中定义的格式匹配完之后,执行此方法进行验证            :return:            """            value = self.cleaned_data['username']            if "666" in value:                raise ValidationError('666已经被玩烂了...', 'invalid')            return value

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

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsfrom django.core.validators import RegexValidator############## 自定义字段 ##############class PhoneField(fields.MultiValueField):    def __init__(self, *args, **kwargs):        # Define one message for all fields.        error_messages = {            'incomplete': 'Enter a country calling code and a phone number.',        }        # Or define a different message for each field.        f = (            fields.CharField(                error_messages={'incomplete': 'Enter a country calling code.'},                validators=[                    RegexValidator(r'^[0-9]+$', 'Enter a valid country calling code.'),                ],            ),            fields.CharField(                error_messages={'incomplete': 'Enter a phone number.'},                validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid phone number.')],            ),            fields.CharField(                validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.')],                required=False,            ),        )        super(PhoneField, self).__init__(error_messages=error_messages, fields=f, require_all_fields=False, *args,                                         **kwargs)    def compress(self, data_list):        """        当用户验证都通过后,该值返回给用户        :param data_list:        :return:        """        return data_list############## 自定义插件 ##############class SplitPhoneWidget(widgets.MultiWidget):    def __init__(self):        ws = (            widgets.TextInput(),            widgets.TextInput(),            widgets.TextInput(),        )        super(SplitPhoneWidget, self).__init__(ws)    def decompress(self, value):        """        处理初始值,当初始值initial不是列表时,调用该方法        :param value:        :return:        """        if value:            return value.split(',')        return [None, None, None]

初始化数据

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

一、Form

from django.forms import Formfrom django.forms import widgetsfrom django.forms import fieldsfrom django.core.validators import RegexValidatorclass PublishForm(Form):    username = fields.CharField()    pwd = fields.CharField()    email = fields.EmailField()    city = fields.ChoiceField(        choices=((1, '上海'), (2, '北京'),),        widget=widgets.Select    )

二、Views

from django.shortcuts import render, redirectfrom app01.forms import PublishFormdef login(request):    if request.method == 'GET':        value = {            'username': 'root',            'pwd': '123123',            'email': 'aaa@163.com',            'city':2,        }                                   #这些值应该是从数据库中获取的数据,前面是form表单定义的name        obj = PublishForm(initial=value)       #设置默认值        return render(request, 'login.html', {'obj': obj})    elif request.method == 'POST':        obj = PublishForm(request.POST)        val = obj.is_valid()        if val:            print(obj.cleaned_data)            return redirect('/index')        else:            print(obj.errors)            return render(request, 'login.html', {'obj': obj})

备注:

三、HTML

<form method="POST" enctype="multipart/form-data">    {% csrf_token %}    <p>{{ obj.username }} {{ obj.username.errors }}</p>    <p>{{ obj.pwd }} {{ obj.errors }}</p>    <p>{{ obj.email }}  {{ obj.errors }}</p>    <p>{{ obj.city }} {{ obj.city.errors }}</p>    <input type="submit" value="提交"/></form>
原创粉丝点击