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

 

posted @ 2018-04-02 15:20  TianTianLi  阅读(207)  评论(0编辑  收藏  举报