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="width: 200px;height: 100px;margin: 0 auto">添加学生</h1>
<div style="width: 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组件中留下了几个方便我们扩展方法。

 

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

 

posted @ 2017-07-05 21:29  九级大狂风  阅读(158)  评论(0编辑  收藏  举报