• Django框架之Form组件


      新手上路                                                             

    From组件的主要功能:

    • 1,对form表单提交的数据进行校验。
      •   内部基于正则进行匹配
    • 2,from表单提交保存上次提交的数据。
      •   生成HTML标签

      初入大荒                                                                

    1,创建Form类

    class StudentForm(Form):
    
        #字段名,最好跟数据库内的字段名一样,好操作
        
        #如CharField,内部包含了正则表达式,
        name = fields.CharField(max_length=12,
                                min_length=2,
                                required=True,
                                widget=widgets.TextInput(attrs={"class":"form-control"}),#添加css样式,标签的class名
                                error_messages={
                                    "max_length":"名字太长了", #错误提示信息
                                    "min_length":"名字太短了",
                                    "required":"名字不能为空",
    
                                })
    
        email = fields.EmailField(widget=widgets.TextInput(attrs={"class":"form-control"}))
    
        age = fields.IntegerField(min_value=10,
                                  max_value=30,
                                  widget=widgets.TextInput(attrs={"class":"form-control"})
                                  )
    
        cls_id = fields.IntegerField(
            widget=widgets.Select(choices=models.Classes.objects.values_list("id","title"),
                                  attrs={"class":"form-control"})
        )
    View Code

    2,Form类对应函数

    def add_student(request):
        if request.method == "GET":
            obj = StudentForm() #实例化对象,在HTML生成input标签
            #print(obj)
            return render(request,"add_student.html",{"obj":obj})
        else:
            obj = StudentForm(request.POST) # request.POST 内包含里提交的所有信息,
            print(obj)
            if obj.is_valid(): #返回值只有True或False
    
                models.Student.objects.create(**obj.cleaned_data) #向数据库中添加数据
                #print(obj.cleaned_data) #这里是提交的所有数据,字典格式,经过内部正则匹配成功的
                return redirect("/student/")
    
            print(obj.errors)  #正则匹配失败的,错误的所有信息
            return render(request, "add_student.html", {"obj": obj})
    View Code

    3,生成HTML

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
    
    </head>
    <body>
    <h1 style=" 200px;height: 100px;margin: 0 auto">添加学生</h1>
    <div style=" 500px;margin: 0 auto;">
    
        <form class="form-horizontal" action="/add_student/" method="POST" novalidate>
            {% csrf_token %}
    
            <div class="form-group">
                <label class="col-sm-2 control-label">姓名:</label>
    
                <div class="col-sm-10">
                    {{ obj.name }}{{ obj.errors.name.0 }}
                </div>
            </div>
    
            <div class="form-group">
                <label class="col-sm-2 control-label">邮箱:</label>
    
                <div class="col-sm-10">
                    {{ obj.email }}{{ obj.errors.email.0 }}
                </div>
            </div>
    
            <div class="form-group">
                <label class="col-sm-2 control-label">年龄:</label>
    
                <div class="col-sm-10">
                    {{ obj.age }}{{ obj.errors.age.0 }}
                </div>
            </div>
    
            <div class="form-group">
                <label class="col-sm-2 control-label">班级:</label>
    
                <div class="col-sm-10">
                    {{ obj.cls_id }}{{ obj.errors.cls_id.0 }}
                </div>
            </div>
    
            <div class="form-group">
                <label class="col-sm-2 control-label"></label>
    
                <div class="col-sm-10">
                    <input type="submit" value="提交">
                </div>
            </div>
    
        </form>
    </div>
    </body>
    </html>
    View Code

      崭露头角                                                                                                     

    创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;

    1、Django中Form类内置字段如下:

    • 常用字段
    '''
    常用字段
    
    CharField  字符串类型
    
    ChoiceField *****
    
    MultipleChoiceField
    
    IntegerField   #整数类型
    
    DateField
    
    DateTimeField  #时间类型
    
    EmailField     #邮件类型
    
    FileField      #文件类型
     
    RegexField     #再次正则匹配
    title = fields.RegexField("鸡蛋w+") 
    
    '''
    • 详细字段
    “”“
    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,Dhango中的Form类插件

    • 常用插件
    复制代码
    class TestForm(Form):
        t1 = fields.CharField(
            widget=widgets.Textarea() #生成文本框标签
        )
    
        #单选
        t2 = fields.CharField(
            widget=widgets.CheckboxInput
        )
    
        #多选
        t3 = fields.MultipleChoiceField(#生成多个checkbox标签
            choices=[(1,"篮球"),(2,"足球"),(3,"乒乓球")],
            widget=widgets.CheckboxSelectMultiple
        )
    
        #radio属性时互斥的,只能选择一个
        t4 = fields.ChoiceField(
            choices=[(1, "篮球"), (2, "足球"), (3,"乒乓球"),(4,"橄榄球")],
            widget=widgets.RadioSelect
        )
    
        t5 = fields.FileField( #文件对象,针对文件类型的
            widget=widgets.FileInput
        )
    • 内置插件
    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,页面展示

    # 灵活用法,生成单个标签
    <form>
        {{obj.xx}}
        {{obj.xx}}
        {{obj.xx}}
        {{obj.xx}}
    </form>

    # 简单用法,局限性大,生成多个标签, #生成多个P标签 {{obj.as_p}} #生成li标签,需要在HTML创建好ul标签,只能生成li标签 <ul> {{obj.as_ul}} </ul> #生成table标签,需要在HTML创建好table标签,只能生成tr,td标签 <table> {{obj.as_table}} </table>

      锋芒毕露                                                               

    单选或者多选时、数据源是否可以实时更新、、、

    在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 (获取的值无法实时更新),需要我们自定义方法来实现,

    方法一:推荐用

    class TeacherForm(Form):
        name = fields.CharField(max_length=12,min_length=2)
        email = fields.EmailField()
        age = fields.IntegerField(max_value=60,min_value=20)
        xx = fields.MultipleChoiceField(
            #choices=models.Classes.objects.values_list("id","title"),
            widget= widgets.SelectMultiple
        )
        def __init__(self,*args,**kwargs):
            '''动态查询数据库信息'''
            super(TeacherForm, self).__init__(*args,**kwargs)
            self.fields["xx"].choices = models.Classes.objects.values_list("id","title")

    方法二:

    使用django提供的ModelChoiceField和ModelMultipleChoiceField字段来实现,用的方面少

    from django.forms import models as form_model
    class TeacherForm(Form):
        name = fields.CharField(min_length=2)
        xx = form_model.ModelMultipleChoiceField(queryset=models.Classes.objects.all())

      名扬万里                                                                   

    上传文件:

    • 方式一:
    #方式一
    def f1(request):
        if request.method == "GET":
            return render(request,"f1.html")
        else:
    
            file_obj = request.FILES.get("file")
    
            f = open(os.path.join("static/images/",file_obj.name),"wb")
            print(file_obj.chunks()) #内容对象
            for chunk in file_obj.chunks():
                f.write(chunk)
                #print(chunk)
            f.close()
            return redirect("/f1/")

     

    方式二:form组件

    #form类
    class FilesForm(Form):
        user = fields.CharField()
        files = fields.FileField()
    
    def f2(request):
        if request.method == "GET":
            obj = FilesForm()
            return render(request,"f2.html",{"obj":obj})
        else:
            obj = FilesForm(data=request.POST,files=request.FILES)
    
            if obj.is_valid():
                print(obj.cleaned_data)
                print(obj.cleaned_data.get("files").name)
                fiel_name = obj.cleaned_data.get("files").name
                fiel = obj.cleaned_data.get("files")
                print(obj.cleaned_data.get("files").size)
    
                f = open(os.path.join("static",fiel_name),"wb")
                for chunk in fiel:
                    f.write(chunk)
                f.close()
    
            return render(request,"f2.html",{"obj":obj})

      震古烁今                                                            

    Django的Form组件提供验证用户提交的数据并可以显示错误信息(或自定制),可以生成相应的Html代码。仅仅根据Form组件的验证或许满足不了一些需求,于是我们再Form的验证功能添加更多的验证功能,Form组件中留下了几个方便我们扩展方法。

    日后再说。。。。。。。。。。。。。

  • 相关阅读:
    Python操作Mongo数据库
    Python正则模块
    Python时间模块
    Python协程(下)
    Python协程(中)
    Python协程(上)
    aiohttp
    常用排序算法的Python实现
    江苏省各地级市58同城租房数据
    百合网
  • 原文地址:https://www.cnblogs.com/gaoyuan111/p/7123318.html
Copyright © 2020-2023  润新知