form 组件

Posted TianTianLi

tags:

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

  • 初始form组件

 

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

 

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

 

  1. 验证功能
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form method="post" action="/form/">
        <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="age">{{ obj.errors.age.0 }}</P>
        <P><input type="text" name="email">{{ obj.errors.email.0 }}</P>
        <p><input type="submit"></p>
    </form>

</body>
</html>
from django import forms
from django.forms import fields


class RegisterForm(forms.Form):
    username = forms.CharField(max_length=20, min_length=6, required=True,
                               error_messages={
                                   \'required\':\'用户名不能为空\',
                                   \'max_length\': \'最大长度20\',
                                    \'min_length\': \'最小长度6\',
                               })
    pwd = forms.CharField(max_length=20, min_length=6, required=True)
    age = forms.IntegerField(required=True)
    email = forms.EmailField(required=True,error_messages={
        \'invalid\':\'格式错误\'
    })
from django.shortcuts import render
from myform.cfrom import RegisterForm
# Create your views here.


def form(request):
    if request.method == \'GET\':
        return render(request, \'forms/index.html\')
    else:
        print(request.POST)
        obj = RegisterForm(request.POST)
        if obj.is_valid():
            print(obj.cleaned_data)
        else:
            print(obj.errors)
    return render(request, \'forms/index.html\',{\'obj\':obj})
  1. 生成input标签功能
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form method="post" action="/form/" novalidate>
        <P>{{ form_obj.username }}{{ form_obj.errors.username.0 }}</P>
        <P>{{ form_obj.pwd }}{{ form_obj.errors.pwd.0 }}</P>
        <P>{{ form_obj.age }}{{ form_obj.errors.age.0 }}</P>
        <P>{{ form_obj.email }}{{ form_obj.errors.email.0 }}</P>
        <p><input type="submit"></p>
    </form>

</body>
</html>
from django.shortcuts import render
from myform.cfrom import RegisterForm
# Create your views here.


def form(request):
    if request.method == \'GET\':
        form_obj = RegisterForm()
        return render(request, \'forms/index.html\', {\'form_obj\': form_obj})
    else:
        print(request.POST)
        form_obj = RegisterForm(request.POST)
        # obj = RegisterForm(request.POST)
        if form_obj.is_valid():
            print(form_obj.cleaned_data)
        else:
            print(form_obj.errors)
    return render(request, \'forms/index.html\', { \'form_obj\': form_obj})

 form类

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


class RegisterForm(forms.Form):
    username = fields.CharField(
        max_length=20,
        min_length=6,
        required=True,
        widget=widgets.TextInput(attrs={\'v\': \'v1\', \'class\': \'c1\'}),
        initial=\'用户名\',
        label=\'用户名\',
        help_text=\'字母、数字、下划线\',
        disabled=False,
        label_suffix=\':\',
        error_messages={
            \'required\': \'用户名不能为空\',
            \'max_length\': \'最大长度20\',
            \'min_length\': \'最小长度6\',
        },
    )
    pwd = fields.CharField(
        max_length=20,
        min_length=6,
        required=True,
        label=\'密码\',
        widget=widgets.PasswordInput
    )
    age = fields.IntegerField(
        required=True,
        max_value=200,
        min_value=0,
        label=\'年龄\',
    )
    email = fields.EmailField(required=True, error_messages={
        \'invalid\': \'格式错误\'
    },
                              label=\'邮箱\',
                              )
    # 单选select
    city = fields.ChoiceField(
        choices=[
            (1, \'中国\'),
            (2, \'美国\'),
            (3, \'日本\'),
        ],
        initial=1,
        label=\'国籍\',
    )
    # 多选select
    hobby = fields.MultipleChoiceField(
        choices=[
            (1, \'音乐\'),
            (2, \'把妹\'),
            (3, \'约妹\'),
        ],
        initial=[1, 3]
    )

    def __init__(self, *args, **kwargs):
        super(RegisterForm, self).__init__(*args, **kwargs)  # 必须在self.fieLds上面
        self.fields[\'hobby\'].widget.choices = ((1, \'\'), (2, \'嗨嗨\'),)
        #
        # self.fields[\'hobby\'].widget.choices = models.Classes.objects.all().value_list(\'id\', \'caption\')

    # 文件
    img = fields.FileField(
        label=\'图片\'
    )

    # 单选的checkbox
    chk = fields.CharField(
        widget=widgets.CheckboxInput(
            attrs={\'v\': \'v1\', \'class\': \'c1\'}
        ),
        label=\'居住地\'
    )

    # 多选checkbox,值为列表
    dchk = fields.MultipleChoiceField(
        initial=[2, 1],
        choices=((1, \'上海\'),
                 (2, \'北京\'),),
        widget=widgets.CheckboxSelectMultiple,
        label=\'曾住地\'
    )

    # 单选的radio
    rad = fields.CharField(
        widget=widgets.Radioselect(choices=((1, \'\'), (2, \'\'),)),
        label=\'性别\'
    )

    # 单radio,值为字符串
    rad1 = fields.ChoiceField(
        choices=((1, \'\'), (2, \'\'),),
        initial=2,
        widget=widgets.RadioSelect(
            attrs={\'class\': \'ll\'}
        ),
        label=\'媳妇\'
    )

 

注意:

若是要生成 下拉菜单, 尽量不要使用 fields.ChoiceField, 实际在提交的时候总是验证错误。建议使用以下方式生成:

from django import forms
from django.forms import fields
from django.forms import widgets
from app01 import models


def get_column_list():
    choices = models.ArticleColumn.objects.all().values_list(\'id\', \'column\')
    return choices


class ArticlePostForm(forms.Form):
    choice = get_column_list()

    def __init__(self, *args, **kwargs):
        super(ArticlePostForm, self).__init__(*args, **kwargs)  # 必须在self.fieLds上面
        self.fields[\'column\'].widget.choices = get_column_list()

    title = fields.CharField(
        required=True,
        error_messages={
            \'required\': \'标题为空...\'
        }
    )

    column = forms.CharField(
        required=True,
        widget=widgets.Select
          )

    body = fields.CharField(
        required=True,
        widget=widgets.Textarea,
        error_messages={
            \'required\': \'内容为空...\'
        }
    )

 

验证流程图:

 

 

流程详解

  1. 函数full_clean()依次调用每个field的clean()函数,该函数针对field的max_length,unique等约束进行验证,如果验证成功则返回值,否则抛出ValidationError错误。如果有值返回,则放入form的cleaned_data字典中。
  2. 如果每个field的内置clean()函数没有抛出ValidationError错误,则调用以clean_开头,以field名字结尾的自定义field验证函数。验证成功和失败的处理方式同步骤1。
  3. 最后,调用form的clean()函数——注意,这里是form的clean(),而不是field的clean()——如果clean没有错误,那么它将返回cleaned_data字典。
  4. 如果到这一步没有ValidationError抛出,那么cleaned_data字典就填满了有效数据。否则cleaned_data不存在,form的另外一个字典errors填上验证错误。在template中,每个field获取自己错误的方式是:{{ form.username.errors }}。
  5. 最后,如果有错误is_valid()返回False,否则返回True。

注意一点:自定义验证机制时:clean()和clean_<field>&()的最后必须返回验证完毕或修改后的值.

 

也就是说,自定义clean_fields 时,返回的是验证过的字段数据。自定义clean() 是在最后一步,要返回完整的clean_data.

 

# 自定义验证  验证password
    def clean_password(self):
        user_data = cleaned_data.get(\'password\')
        if user_data == \'XXX\':
            raise forms.ValidationError(u\'密码太简单了\')
        return user_data

  

# 验证选择婚姻是否正确
    def clean_marry(self):
        data_list = self.cleaned_data[\'marry\']
        if len(data_list) == 2:
            if \'0\' and \'1\' in data_list:
                raise forms.ValidationError(\'男女选择有误!\')
            elif \'2\' and \'3\' in data_list:
                raise forms.ValidationError(\'婚姻选择有误!\')
            else:
                return data_list
        else:
            raise forms.ValidationError(\'请选择男女和婚姻!\')
    def clean(self):
        cleaned_data = self.cleaned_data
        pwd = cleaned_data[\'pwd\']

        pwd2 = cleaned_data[\'pwd2\']
        print(pwd,pwd2)
        if pwd != pwd2:
            raise forms.ValidationError(\'二次输入密码不匹配\')
        return cleaned_data #注意此处一定要return clean_data,否则会报错
        
        

 自定义验证规则

方式一:

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

方式二:

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\'手机号码\'}))

参考文档:http://www.cnblogs.com/wupeiqi/articles/6144178.html

 

class RegistrationForm(forms.Form):

    username = fields.CharField(
        required=True,
        error_messages={
            \'required\': \'输入用户名...\'
        }
    )
    email = fields.EmailField(
        required=True,
        error_messages={
            \'required\': \'输入邮箱...\',
            \'invalid\':\'格式错误...\'
        }
    )

    password = fields.CharField(
        required=True,
        min_length=6,
        label=\'密码\',
        widget=widgets.PasswordInput,
        error_messages={
            \'required\': \'输入密码...\',
            \'min_length\': \'最小长度为6...\'
        }
    )
    password_again = fields.CharField(
        required=True,
        widget=widgets.PasswordInput,
        label=\'确认密码\',
        error_messages = {
            \'required\': \'输入密码...\',
        }
    )

    def clean_username(self):
        username = self.cleaned_data[\'username\']
        ret = UserInfo.objects.filter(username=username)
        if ret.exists():
            raise forms.ValidationError(\'用户名已存在...\')
        return username

    def clean(self):
        clean_data = self.cleaned_data
        if not self.errors:
            password1 = clean_data[\'password\']
            password2 = clean_data[\'password_again\']
            if password1 != password2:
                raise forms.ValidationError(\'两次密码不一致...\')
        return clean_data

 

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

maven web项目的web.xml报错The markup in the document following the root element must be well-formed.(代码片段

django—Form组件

Django—分页器与form组件

django之forms组件

微信小程序代码片段

Django框架之Form组件