• Django Form表单


     阅读目录

     

    构建一个表单

    导入模块

    from django import forms
    from django.forms import widgets
    from django.core.exceptions import ValidationError
    

      

    创建form类

    from django import forms
    from django.forms import widgets
    from django.core.exceptions import ValidationError
    import re
    from django.contrib.auth.models import User
    
    
    class LoginForm(forms.Form):
        # 字段名字(username)就是渲染后input标签的name属性
        username = forms.CharField(min_length=2, max_length=8,
                                   strip=True,  # 是否移除用户输入空白
                                   # error_messages 为错误触发的错误信息
                                   error_messages={"required": "该字段不能为空",
                                   "min_length": "用户名长度不能小于2",
                                   "max_length": "用户名长度不能大于8"},
                                   # 给input添加属性
                                   widget=widgets.TextInput(attrs={
                                       "class": "form-control",
                                       "placeholder": "2-8 位中文/字母/下划线",
                                       "id": "inputname"}))
    
        password = forms.CharField(min_length=6,max_length=20,
                                   strip=True,
                                   error_messages={"required":"该字段不能为空",
                                  "min_length":"密码长度不能小于6位",
                                  "max_length":"密码长度不能大于20位"},
                                   widget = widgets.PasswordInput(attrs={
                                       "class":"form-control",
                                       "placeholder":"密码需6-20个字符",
                                       "id":"inputPassword3"}))
    
        check_pwd = forms.CharField(min_length=6,max_length=20,
                                    strip=True,
                                   error_messages={"required":"该字段不能为空",
                                  "min_length":"密码长度不能小于6位",
                                  "max_length":"密码长度不能大于20位"},
                                   widget = widgets.PasswordInput(attrs={
                                       "class":"form-control",
                                       "placeholder":"请再次输入密码",
                                       "id":"inputPassword4"}))
    
        email = forms.EmailField(error_messages={'required': "邮箱不能为空", "invalid":"请输入有效的邮箱地址"},
                                 widget = widgets.EmailInput(attrs={
                                     "class":"form-control",
                                     "placeholder":"请输入邮箱",
                                     "id":"inputemail"}))

     

    视图

    from .forms import LoginForm
    
    def form_reg(request):
        if request.method == "POST":
            login_form = LoginForm(request.POST)  # 将数据传给对应字段  绑定数据的表单实例
    
            if login_form.is_valid():  # 判读是否全部通过验证
                print("通过验证")
                print(login_form.cleaned_data)  # 保存全部通过验证的表单数据 {'username': '周军豪123', 'password': '961023hao'}
                username = login_form.cleaned_data.get("username")
                password = login_form.cleaned_data.get("password")
                User.objects.create_user(username=username, password=password)
                print("数据库保存成功")
                return redirect("/log_in/")
            else:
                errors = login_form.errors  # 字典类型,键是字段名,值是一个存着所有错误信息的列表 莫版中用{{ errors.字段名.0 }}
                # print(type(login_form.errors))# <class 'django.forms.utils.ErrorDict'>
                # login_form.errors={"user":["小于5位","不是数字"],"pwd":["",""]}
                
                error_all = errors.get("__all__")  
               #全局钩子的错误信息保存在了键是 __all__ 的值的列表中,在模版语言中用{{ error_all.0 }}
                print(error_all)
                return render(request, "form_reg.html", {"errors": errors, "error_all":error_all, "login_form": login_form})
       else:
       login_form
    = LoginForm() # form组件的实例对象 未绑定表单实例 GET请求时渲染出input标签
         return render(request, "form_reg.html", {"login_form": login_form})

     

    回到顶部

    模版

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!-- 新 Bootstrap 核心 CSS 文件 -->
        <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
        <style>
            .container{
                margin-top: 100px;
    
            }
        </style>
    </head>
    <body>
    
    
    <div class="container">
        <div class="row">
            <div class="col-md-6">
    
                <form action="/login/" method="post">
                     {% csrf_token %}
                      <div class="form-group">
                        <label for="user">user</label>
                        {{ login_form.user }} <span>{{ errors.user.0 }}</span>
                      </div>
                      <div class="form-group">
                        <label for="pwd">pwd</label>
                        {{ login_form.pwd }} <span>{{ errors.pwd.0 }}</span>
                      </div>
                       <div class="form-group">
                        <label for="gender">gender</label>
                        {{ login_form.gender }}<span>{{ error_all.0 }}</span>
                      </div>
    
                     <p>{{ login_form.usersss }}</p>
    
                      <button type="submit" class="btn btn-default">Submit</button>
                    </form>
                <hr>

    {# <form action="">#} {# {{ login_form.as_p }}#} {# </form>#} </div> </div> </div> </body> </html>

     

    Django Form 类详解

    绑定的和未绑定的表单实例

    绑定的和未绑定的表单 之间的区别非常重要:

    • 未绑定的表单没有关联的数据。当渲染给用户时,它将为空或包含默认的值。
    • 绑定的表单具有提交的数据,因此可以用来检验数据是否合法。如果渲染一个不合法的绑定的表单,它将包含内联的错误信息,告诉用户如何纠正数据。

    字段详解

    Widgets

    每个表单字段都有一个对应的Widget 类,它对应一个HTML 表单Widget,例如<input type="text">

    在大部分情况下,字段都具有一个合理的默认Widget。例如,默认情况下,CharField 具有一个TextInput Widget,它在HTML 中生成一个<input type="text">

     

    字段的数据

    不管表单提交的是什么数据,一旦通过调用is_valid() 成功验证(is_valid() 返回True),验证后的表单数据将位于form.cleaned_data 字典中。这些数据已经为你转换好为Python 的类型。

    注:此时,你依然可以从request.POST 中直接访问到未验证的数据,但是访问验证后的数据更好一些。

    在上面的联系表单示例中,is_married将是一个布尔值。类似地,IntegerField 和FloatField 字段分别将值转换为Python 的int 和float

    表单字段详细参考:http://blog.csdn.net/qq_14898613/article/details/61617007

    使用表单模版

    表单渲染的选项

    对于<label>/<input> 对,还有几个输出选项:

    • {{ form.as_table }} 以表格的形式将它们渲染在<tr> 标签中
    • {{ form.as_p }} 将它们渲染在<p> 标签中
    • {{ form.as_ul }} 将它们渲染在<li> 标签中

    注意,你必须自己提供<table> 或<ul> 元素。

    {{ form.as_p }}会渲染如下:

    <form action="">
        <p>
            <label for="id_username">Username:</label> 
            <input id="id_username" maxlength="100" name="username" type="text" required="">
        </p>
    
    
        <p>
            <label for="id_password">Password:</label> 
            <input id="id_password" maxlength="100" name="password" placeholder="password" type="password" required="">
        </p>
    
    
        <p>
            <label for="id_telephone">Telephone:</label> <input id="id_telephone" name="telephone" type="number" required="">
        </p>
    
    
        <p>
            <label for="id_email">Email:</label> <input id="id_email" name="email" type="email" required="">
        </p>
    
    
        <p>
            <label for="id_is_married">Is married:</label> <input id="id_is_married" name="is_married" type="checkbox">
        </p>
    
    
        <input type="submit" value="注册">
    </form>
    View Code

     

    回到顶部

    Form组件的钩子

    局部钩子

        def clean_username(self):  # 函数名必须已clean_字段名的格式
            user = self.cleaned_data.get("username")
            if not User.objects.filter(username=user):
                if not user.isdigit():
                    if re.findall(r"^[A-Za-z0-9_-u4e00-u9fa5]+$",user):
                        return user  # 通过检测,原数据返回 self.cleaned_data.get("username")
                    else:
                        raise ValidationError('用户名存在非法字符')  # 没通过检测抛出错误,必须用ValidationError
    
                else:
                    raise ValidationError("用户名不能为纯数字")
            else:
                raise ValidationError("该用户名已存在")

    全局钩子

        def clean(self):  # 必须命名为clean
            # 判断是否都通过检测,都不为None
            if self.cleaned_data.get("password") and self.cleaned_data.get("check_pwd"):
                if self.cleaned_data.get("password") == self.cleaned_data.get("check_pwd"):
                    return self.cleaned_data  # 如果两次密码相同,返回干净的字典数据
                else:
                    raise ValidationError("输入密码不一致")  # 没通过检测返回异常信息
            else:
                return self.cleaned_data

     

    回到顶部

    form组件补充

    1.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-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类型
        ...
    View Code

    2.Django内置插件

    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
    View Code

    3.常用选择插件

    # 单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
    # )
    View Code
  • 相关阅读:
    kvm虚拟迁移(5)
    kvm虚拟化网络管理(4)
    计算系数
    排列组合
    错排
    加分二叉树
    皇宫看守
    战略游戏
    数字转换
    JDK8 HashMap源码分析
  • 原文地址:https://www.cnblogs.com/zhoujunhao/p/8039501.html
Copyright © 2020-2023  润新知