django-Form组件

1 Form表单定义

from django.forms import Form
from django.forms import fields
from django.forms import widgets
import re
from django.core.exceptions import ValidationError

class UserLogin(Form):
    username = fields.CharField(
        required=True,
        error_messages={'required':'用户名不能为空'},
        widget=widgets.TextInput(attrs={'class':'txtcss_user'})
    )
    password = fields.CharField(
        required=True,
        error_messages={'required': '密码不能为空'},
        widget=widgets.PasswordInput(attrs={'class': 'txtcss_pwd'})
    )

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 SignUpForm(Form):
    username=fields.CharField(
        min_length=5,max_length=20,
        error_messages={'required': '用户名不能为空',
                        'min_length': u'用户名最少为5个字符',
                        'max_length': u'标题最多为20个字符',
                        },
        widget=widgets.TextInput(attrs={"class": "txtcss_usual txt_username",'placeholder': u'用户名5-20个字符'})
    )
    phone = fields.CharField(
        validators=[mobile_validate, ],
        error_messages={'required': '手机号不能为空'},
        widget=widgets.TextInput(attrs={"class": "txtcss_usual",'placeholder': u'手机号码'})
    )
    password=fields.CharField(
        min_length=5,
        error_messages={'required': '密码不能为空','min_length': u'密码最少为5个字符',},
        widget=widgets.PasswordInput(attrs={"class": "txtcss_usual",'placeholder': u'密码'})
    )
    pwd_confirm=fields.CharField(
        error_messages={'required': '确认密码不能为空'},
        widget=widgets.PasswordInput(attrs={"class": "txtcss_usual",'placeholder': u'确认密码'})
    )
    email=fields.EmailField(
        required=False,
        error_messages={'required': '邮箱不能为空','invalid': u'邮箱格式错误'},
        widget=widgets.TextInput(attrs={"class": "txtcss_usual",'placeholder': u'邮箱'})
    )
    def clean(self):
        pwd = self.cleaned_data.get("password")
        pwd_confirm = self.cleaned_data.get("pwd_confirm")
        if pwd == pwd_confirm:
            return self.cleaned_data
        else:
            self.add_error("pwd_confirm",ValidationError("密码输入不一致"))
            return self.cleaned_data

 2 Form表单使用

2.1 views视图

if request.method == 'POST':
    response = {'status': True, 'data': None, 'msg': None, 'query': None}
    valid_code = request.POST.get("valid_code")
    session_valid = request.session.get("valid_code")
    if valid_code.upper() == session_valid.upper():
        regForm = forms.SignUpForm(request.POST)
        if regForm.is_valid():
            username=regForm.cleaned_data.get("username")
            password=regForm.cleaned_data.get("password")
            email=regForm.cleaned_data.get("email")
            phone = regForm.cleaned_data.get("phone")
            user=models.UserInfo.objects.create_user(
                username=username,
                password=password,
                email=email,
                telephone=phone,
            )
        else:
            print(regForm.errors)
            response["status"] = False
            response["msg"]=regForm.errors  # errors只存错误字段
    else:
        response['status'] = False
        response['query'] = '验证码错误。'
    return HttpResponse(json.dumps(response))
else:
    regForm = forms.SignUpForm()
    return render(request,'signup.html',{"form":regForm})

2.2 模板中的signup.html

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
    <link rel="stylesheet" href="{% static 'dist/css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="{% static 'css/login.css' %}">
    <link rel="stylesheet" href="{% static 'css/_layout.min.css' %}">
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-10 col-md-offset-1"
             style="border-radius: 8px;border: 1px solid #e1e1e8;margin-top: 100px;padding-bottom:30px;padding-top: 10px;">
            <div class="row">
                <div class="col-md-10 col-md-offset-1" style="border-bottom: 1px solid #e1e1e8;margin-bottom: 30px;">
                    <h3>注册新用户</h3>
                </div>
            </div>
            <div class="row">
                <div class="col-md-12" style="line-height: 50px;font-size: 18px;">
                    <form id="form1">
                        <div class="row">
                            <div class="col-md-4" style="text-align: right;">
                                <label for="username">用户名:</label>
                            </div>
                            <div class="col-md-8">{{ form.username }}</div>
                            <input id="is_exist_user" type="hidden" value="False" />
                        </div>
                        <div class="row">
                            <div class="col-md-4" style="text-align: right;">
                                <label for="email">邮箱:</label>
                            </div>
                            <div class="col-md-8">{{ form.email }}</div>
                        </div>
                        <div class="row">
                            <div class="col-md-4" style="text-align: right;">
                                <label for="phone">手机号:</label>
                            </div>
                            <div class="col-md-8">{{ form.phone }}</div>
                        </div>
                        <div class="row">
                            <div class="col-md-4" style="text-align: right;">
                                <label for="password">密码:</label>
                            </div>
                            <div class="col-md-8">{{ form.password }}</div>
                        </div>
                        <div class="row">
                            <div class="col-md-4" style="text-align: right;">
                                <label for="pwd_confirm">确认密码:</label>
                            </div>
                            <div class="col-md-8">{{ form.pwd_confirm }}</div>
                        </div>
                        <div class="row">
                            <div class="col-md-4" style="text-align: right;">
                                <label for="valid_code">验证码:</label>
                            </div>
                            <div class="col-md-8">
                                <input type="text" name="valid_code" class="txtcss_code" placeholder="验证码"/>
                                <a href="#"><img class="valid_img" src="/get_valid_img/" mypath="/get_valid_img/"
                                                 alt="ok" width="200" height="40"></a>
                            </div>
                        </div>
                        <div class="row" style="margin-top: 10px;">
                            <div class="col-md-7" style="text-align: right;">
                                <a href="#" class="btn btn-primary btn-lg" style="width:150px" onclick="submitForm();"
                                   id="submit">注册</a>
                            </div>
                            <div class="col-md-5">
                                <span id="login_fail"></span>
                            </div>
                            {% csrf_token %}
                        </div>
                    </form>

                </div>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12" style="text-align: center;font-size: 16px; margin-top: 30px;">
            &copy; 2017-2020 www.ship.com.cn All Rights Reserved.我的博客 版权所有
        </div>
    </div>
</div>

<script src="{% static 'js/jquery-2.2.0.min.js' %}"></script>
<script src="{% static 'js/jquery.cookie.js' %}"></script>
<script src="{% static 'js/jquery.myConfirm.js' %}"></script>
<script src="{% static 'js/nav-iconfont.js' %}"></script>
<script src="{% static 'js/_layout.min.js' %}"></script>
<script type="text/javascript">
     $(".valid_img").click(function () {
         console.log($(this).attr("mypath")+Math.random());
         $(this)[0].src=$(this).attr("mypath")+Math.random();
     });

     $(".txt_username").blur(function () {
         var username = $(this).val();
         // 判断输入框是否为空
         if (username == ""){
             return false;
         }
         $.ajax({
            url: '/valid_username/',
            type: 'POST',
            data: {"username":username,"csrfmiddlewaretoken":$("input[name='csrfmiddlewaretoken']").val()},
            dataType: 'JSON',
            success: function (arg) {
                if (arg.status) {
                    $("#is_exist_user").val("True");
                    var tag = document.createElement('span');
                    tag.innerHTML = "用户名存在";
                    tag.className = "error";
                    $('#form1 input[name="username"]').after(tag);
                }
                else {
                    $("#is_exist_user").val("False");
                }
            }
        })
     });

    function submitForm() {
        if($("#is_exist_user").val()=="True"){
            return false;
        }
        $('#form1 .error').remove();
        $.ajax({
            url: '/signup/',
            type: 'POST',
            data: $('#form1').serialize(),
            dataType: 'JSON',
            success: function (arg) {
                if (arg.status) {
                    location.href = "/login/";
                } else {
                    if (arg.query) {
                        var tag = document.createElement('span');
                        tag.innerHTML = arg.query;
                        tag.className = "error";
                        $('#login_fail').after(tag);
                    }
                    $.each(arg.msg, function (k, v) {
                        var tag = document.createElement('span');
                        tag.innerHTML = v[0];
                        tag.className = "error";
                        $('#form1 input[name="' + k + '"]').after(tag);
                    })
                }
            }
        })
    }
</script>

</body>
</html>
signup.html

3 Form表单钩子

class SignUpForm(Form):
    username=fields.CharField(
        min_length=5,max_length=20,
        error_messages={'required': '用户名不能为空',
                        'min_length': u'用户名最少为5个字符',
                        'max_length': u'标题最多为20个字符',
                        },
        widget=widgets.TextInput(attrs={"class": "txtcss_usual txt_username",'placeholder': u'用户名5-20个字符'})
    )
    password=fields.CharField(
        min_length=5,
        error_messages={'required': '密码不能为空','min_length': u'密码最少为5个字符',},
        widget=widgets.PasswordInput(attrs={"class": "txtcss_usual",'placeholder': u'密码'})
    )
    pwd_confirm=fields.CharField(
        error_messages={'required': '确认密码不能为空'},
        widget=widgets.PasswordInput(attrs={"class": "txtcss_usual",'placeholder': u'确认密码'})
    )
    def clean(self):
        pwd = self.cleaned_data.get("password")
        pwd_confirm = self.cleaned_data.get("pwd_confirm")
        if pwd == pwd_confirm:
            return self.cleaned_data
        else:
            self.add_error("pwd_confirm",ValidationError("密码输入不一致"))
            return self.cleaned_data

4 内置字段

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类型

5 内置插件

TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget

6 常用插件

# 单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
)
posted @ 2017-12-07 11:29  平凡执着  阅读(356)  评论(0编辑  收藏  举报