9.24 Django Form组件

2018-9-23 20:10:04

这两天优化了自己图书管理系统

github 连接:https://github.com/TrueNewBee/pythonDemo

顺便整理了博客,写了好多总结,都发表自己博客文章了

放上连接 https://www.cnblogs.com/zhen1996/category/1306698.html

明天再看 day73视频

form 参考连接:http://www.cnblogs.com/liwenzhou/p/8747872.html

2018-9-24 14:28:04

2018-9-24 19:42:38

昨天成功爬取拉勾网 很好玩的 今晚打算做成excel表格

直接贴上源代码:

# views

class RegForm(forms.Form):
    name = forms.CharField(
        max_length=16,
        label='用户名',
        widgets=widgets.TextInput(attrs={"class": "form-control"})
    )
    pwd = forms.CharField(
        # 校验规则相关
        label='密码',
        min_length=6,
        # widget 控制生成html代码相关的
        widgets=widgets.PasswordInput(attrs={"class": "form-control"}),
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短6位"
        })
    re_pwd = forms.CharField(
        label='密码',
        min_length=6,
        widgets=widgets.PasswordInput(attrs={"class": "form-control"}),
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短6位",
        })

    email = forms.EmailField(
        label="邮箱",
        widget=widgets.EmailInput(attrs={"class": "form-control"}),
        error_messages={
            "required": "不能为空",
        })
    mobile = forms.CharField(
        label="手机",
        # 自己定制校验规则
        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'),
                    RegexValidator(r'^1[3-9][0-9]{9}$', '手机格式有误')
                    ],
        widget=widgets.TextInput(attrs={"class": "form-control"}),
        error_messages={
            "required": "不能为空",
        })

    gender = forms.fields.ChoiceField(
        choices=((1, ""), (2, ""), (3, "保密")),
        label="性别",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )
    # 单选 Select
    hobby1 = forms.fields.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=3,
        widget=forms.widgets.Select()
    )
    # 多选Select
    hobby2 = forms.fields.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )
    # 单选checkbox
    keep = forms.fields.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )
    # 多选checkbox
    hobby3 = forms.fields.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple(attrs={"class": "c1"})
    )
    # 动态从数据库区choices数据
    city = forms.fields.MultipleChoiceField(
        choices=models.City.objects.all().values_list(),
        label="城市",
        initial=1,
        widget=forms.widgets.SelectMultiple()
    )

    # 重写父类的init方法
    # 实时更新数据库内容
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['city'].widget.choices = models.City.objects.all().values_list('id', 'name')

    def clean_name(self):
        value = self.cleaned_data("name")
        if "Alex" in value:
            raise ValidationError("不符合社会主义核心价值观")
        return value

    # 重写父类的clean方法
    def clean(self):
        # 此时 通过检验的字段的数据都保存在 self.cleaned_data
        pwd = self.cleaned_data.get("pwd")
        re_pwd = self.cleaned_data.get("re_pwd")
        if pwd != re_pwd:
            self.add_error("re_pwd", ValidationError("两次密码不一致"))
            raise ValidationError("两次密码不一致")
        return self.cleaned_data


def reg2(requests):
    form_obj = RegForm()
    if requests.method == 'POST':
        form_obj = RegForm(requests.POST)
        # 让form帮我们做校验
        if form_obj.is_valid():
            # 校验通过
            # 把数据存到数据库
            # 所有经过校验的数据都保存在  form_obj.cleaned_data
            del form_obj.cleaned_data["red_pwd"]
            models.UserInfo.objects.create(**form_obj.cleaned_data)
            return HttpResponse("注册成功")
    return render(requests, 'reg2.html', {'form_obj': form_obj})

models

from django.db import models

# Create your models here.


class UserInfo(models.Model):
    name = models.CharField(max_length=32, unique=True, null=False)
    pwd = models.CharField(max_length=32, default='doushidashuaibi')
    email = models.EmailField(null=True)
    mobile = models.CharField(max_length=11, null=True)

    def __str__(self):
        return self.name


class City(models.Model):
    name = models.CharField(max_length=16, null=True, unique=True)

    def __str__(self):
        return self.name

reg2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Django Form组件使用</title>
    <style>
        .c1 {
            list-style-type: none;
        }
    </style>
</head>
<body>

{#<form action="/reg2/" method="post">#}
{#    {% csrf_token %}#}
{#    {{form_obj.as_p }}#}
{#    {{form_obj.errors.pwd }}#}
{#    <p><input type="submit"></p>#}
{#</form>#}

<!--自己逐个字段写-->
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <form action="/reg2/" method="post" novalidate>
                {% csrf_token %}
                <div class="form-group {% if form_obj.name.errors.0 %}has-error{% endif %}">
                    {{ form_obj.name.label }}
                    {{ form_obj.name }}
                    <span class="help-block">{{ form_obj.name.errors.0 }}</span>
                </div>

                <div class="form-group {% if form_obj.pwd.errors.0 %}has-error{% endif %}">
                    {{ form_obj.pwd.label }}
                    {{ form_obj.pwd }}
                    <span class="help-block">{{ form_obj.pwd.errors.0 }}</span>
                </div>
                <div class="form-group {% if form_obj.re_pwd.errors.0 %}has-error{% endif %}">
                    {{ form_obj.re_pwd.label }}
                    {{ form_obj.re_pwd }}
                    <span class="help-block">{{ form_obj.re_pwd.errors.0 }}</span>
                </div>
                <div class="form-group {% if form_obj.email.errors.0 %}has-error{% endif %}">
                    {{ form_obj.email.label }}
                    {{ form_obj.email }}
                    <span class="help-block">{{ form_obj.email.errors.0 }}</span>
                </div>
                <div class="form-group {% if form_obj.mobile.errors.0 %}has-error{% endif %}">
                    {{ form_obj.mobile.label }}
                    {{ form_obj.mobile }}
                    <span class="help-block">{{ form_obj.mobile.errors.0 }}</span>
                </div>


                <div class="form-group {% if form_obj.city.errors.0 %}has-error{% endif %}">
                    {{ form_obj.city.label }}
                    {{ form_obj.city }}
                    <span class="help-block">{{ form_obj.city.errors.0 }}</span>
                </div>
                <div class="form-group">
                    <input type="submit" class="btn btn-default">
                </div>
            </form>
        </div>
    </div>

</div>
</body>
</html>

Django Form所有内置字段

Field
    required=True,               是否允许为空
    widget=None,                 HTML插件
    label=None,                  用于生成Label标签或显示内容
    initial=None,                初始值
    help_text='',                帮助信息(在标签旁边显示)
    error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}
    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类型

Django Form内置字段

  

day73 2018-05-17

1. 内容回顾
    1. 回顾了一下json数据格式
        1. JS对象        和 json数据格式的互相转换
        2. Python中数据  和 json数据格式的互相转换
    2. AJAX
        1. 我们前端往后端发请求的方式:
            1. 直接在地址栏输入URL
            2. a标签
            3. form表单
            4. AJAX
            
            HTTP请求的类型:
                GET
                POST
        2. AJAX特点:
            1. 异步
            2. 局部刷新(偷偷发请求)
            
        3. AJAX缺点:
            请求零碎,滥用对服务端压力大
        
        4. jQuery封装的AJAX方法:
            先导入 jquery.js 
            
            $.ajax({
                url: "/test/",
                type: "post",
                data: {"key": "value", "key2":[[1, 2, 3], [4, 5, 6]]},
                success: function(arg){
                    // 请求得到响应的时候,自动执行这个回调函数
                    console.log(arg);
                }
            })
            
2. 今日内容
    1. form组件的介绍
        
    之前web开发的模式,以注册为例:
        1. 要有一个注册的页面,页面里面要有form表单        --> 生成HTML代码
        2. form表单要能提交数据到后端,后端要做有效性校验  --> 数据有效性校验
        3. 要把校验的提示信息展示在页面上                  --> 校验信息返回并展示,保存原来填写的内容
        
        
        关于校验:
            1. 前端通过JS代码做校验    --> 最好有
            2. 后端做校验              --> 必须要有(因为前端的校验可以被跳过)
        
        
    2. form组件的用法
        1. from django import forms
        2, 定义一个form类
            class RegForm(forms.Form):
                user = forms.CharField()
                pwd = forms.CharField()
                email = forms.EmailField()
        
        生成HTML:
            3. 实例化一个form对象, 传递到模板语言中
            4. 在目标语言中调用form对象的响应方法和属性
            
            三种方式:
                1. {{ form_obj.as_p }}
                2. 单独写
                    {{ form_obj.pwd.label }}
                    {{ form_obj.pwd }}
        
        
        做校验:
            1. form_obj = RegForm(request.POST)
            2. form_obj.is_valid()
            
        内置的正则校验器的使用
            mobile = forms.CharField(
                label="手机",
                # 自己定制校验规则
                validators=[
                    RegexValidator(r'^[0-9]+$', '手机号必须是数字'),
                    RegexValidator(r'^1[3-9][0-9]{9}$', '手机格式有误')
                ],
                widget=widgets.TextInput(attrs={"class": "form-control"}),
                error_messages={
                    "required": "该字段不能为空",
                }
            )
    
    看源码:
        
    
        form_obj.is_valid()都干了什么?
        
        
        self._errors = ErrorDict()  --> {}
        self.cleaned_data = {}     

        self.fields.items()
            字段名  字段对象
        
        
        如果有错误:
            self._errors["name"] = ""
        
        没有报错:
            self.cleaned_data["name"] = value(用户填写的值)
            
        注意:
        钩子函数(hook)的使用
        
        def clean_xx():
            """具体字段的自定义校验方法"""
            pass
        
        def clean():
            """全局的自定义校验方法"""
            pass
        

errors:
        
<ul class="errorlist">
    <li>name
        <ul class="errorlist">
            <li>不符合社会主义核心价值观!</li>
        </ul>
    </li>
    <li>__all__
        <ul class="errorlist nonfield">
            <li>两次密码不一致</li>
        </ul>
    </li>
</ul>
原文地址:https://www.cnblogs.com/zhen1996/p/9693644.html