zoukankan      html  css  js  c++  java
  • django下Form表单的使用

    一、什么是Form?什么是Django Form?
    django表单系统中,所有的表单类都作为django.forms.Form的子类创建,包括ModelForm
    关于django的表单系统,主要分两种

    基于django.forms.Form:所有表单类的父类
    基于django.forms.ModelForm:可以和模型类绑定的Form

    实例:
    实现添加出版社信息的功能

    以下表单都是基于如下models.py中的Publisher类实现的:

    from django.db import models
    
    class Publisher(models.Model):
        name = models.CharField(max_length=30, verbose_name="名称")
        address = models.CharField("地址", max_length=50)
        city = models.CharField('城市',max_length=60)
        state_province = models.CharField('省份',max_length=30)
        country = models.CharField('国家',max_length=50)
        website = models.URLField('网址',)
    
        class Meta:
            verbose_name = '出版商'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    class Author(models.Model):
        name = models.CharField(max_length=30)
    
    class AuthorDetail(models.Model):
        sex = models.BooleanField(max_length=1, choices=((0, '男'),(1, '女'),))
        email = models.EmailField()
        address = models.CharField(max_length=50)
        birthday = models.DateField()
        author = models.OneToOneField(Author)
    
    class Book(models.Model):
        title = models.CharField(max_length=100)
        authors = models.ManyToManyField(Author)
        publisher = models.ForeignKey(Publisher)
        publication_date = models.DateField()
        price = models.DecimalField(max_digits=5,decimal_places=2,default=10.00)
    

      

    二、不使用Django Form的情况(原生的写html实现表单提交)

    add_publisher.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>添加出版社信息</title>
    </head>
    <body>
     <form action="{% url 'add_publisher' %}" method="post">
         {% csrf_token %}
         名称:<input type="text" name="name"><br>
         地址:<input type="text" name="address"><br>
         城市:<input type="text" name="city"><br>
         省份:<input type="text" name="state_province"><br>
         国家:<input type="text" name="country"><br>
         网址:<input type="text" name="website"><br>
         <input type="submit" value="添加"><br>
    </body>
    </html>
    

      

    views中的控制语句:

    from django.shortcuts import render,render_to_response,redirect
    from django.contrib.auth.models import User
    from django.http import HttpRequest,HttpResponse
    from django.template import loader
    import datetime
    from hello.models import Publisher
    
    
    def add_publisher(request):
    if request.method == "POST":
    #不使用Form情况时,如果为post提交,去接收用户提交过来的数据
    print(request.POST)
    return HttpResponse("添加信息成功")
    # 使用django Form表单提交

    else:
    return render(request,'add_publisher.html',locals())

    启动服务

    查看功能页面:

     比如提交如下内容:

    控制端查看提交结果:

    发现提交结果以字典的方式显示如下:

    <QueryDict: {'state_province': ['北京'], 'website': ['http://www.tup.tsinghua.edu.cn'], 'address': ['北京市xxx路'], 'country': ['中国'], 'name': ['清华大学出版社'], 'csrfmiddlewaretoken': ['vkk9K0fT0FATXoIHQ5El2OLyULJUszrs'], 'city': ['北京市']}>

    接下来修改views.py中add_publisher类将提交内容写入数据库:

    from django.shortcuts import render,render_to_response,redirect
    from django.contrib.auth.models import User
    from django.http import HttpRequest,HttpResponse
    from django.template import loader
    import datetime
    from hello.models import Publisher
    
    def add_publisher(request):
        if request.method == "POST":
            #不使用Form情况时,如果为post提交,去接收用户提交过来的数据
             name = request.POST['name']
             address = request.POST['address']
             city = request.POST['city']
             state_province = request.POST['state_province']
             country = request.POST['country']
             website = request.POST['website']
    #将提交的结果写入数据库 Publisher.objects.create( name=name, address=address, city=city, state_province=state_province, website=website, ) #print(request.POST) return HttpResponse("添加信息成功") # 使用django Form表单提交 else: return render(request,'add_publisher.html',locals())

    添加测试内容:

    添加测试内容之前:

    提交上述内容之后:

    提交页面显示提交成功,再看下数据库:

    发现提交内容被写入数据库,说明提交内容可以正常写入数据库,那如果提交内容为空,即什么都不写呢?

    添加--->

    再看下数据库:

    发现多了一条空内容,即提交的时候全为空也可以提交成功并写入数据库。

    所以这里明显一个缺陷是少了一个验证功能,即提交内容不能全为空,如果为空则提示必须填写相关项,接下来使用Form来实现表单的验证功能。

    三、使用Form的情况

    如果使用Form的话需要在我们的app里面添加一个模块,这里将模块命名为forms.py,内容如下

    from django import forms
    
    class PublisherForm(forms.Form):
            name = forms.CharField()
            address = forms.CharField()
            city = forms.CharField()
            state_province = forms.CharField()
            country = forms.CharField()
            website = forms.URLField()
    

    注释:PublisherForm类继承django中的forms模块下的Form类,从而成为Form类的子类,Form类中的所有属性PublisherForm类中都会继承下来,所以就可以通过forms类的相关字段来定义的name、address、city、state_province、country、website属性。

    接下来在models.py中导入定义的forms.py。

    from hello.forms import PublisherForm
    然后在views.py中对定义的PublisherForm类进行实例化成对象publisher_form,实现代码入下:
    from django.shortcuts import render,render_to_response,redirect
    from django.contrib.auth.models import User
    from django.http import HttpRequest,HttpResponse
    from django.template import loader
    import datetime
    from hello.models import Publisher
    from hello.forms import PublisherForm
    
    def add_publisher(request):
        if request.method == "POST":      
             # 使用django Form表单提交
             pass
        else:
              publisher_form = PublisherForm() #定义一个实例来接收初始化的PublisherForm类
              return render(request,'add_publisher.html',locals())
    

     当实现了实例化对象publisher_form之后,name在模板中就可以接收实例化对象,然后显示到页面,实现代码入下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>添加出版社信息</title>
    </head>
    <body>
     <form action="{% url 'add_publisher' %}" method="post">
         {% csrf_token %}
         {{ publisher_form.as_p }}
         <input type="submit" value="添加"><br>
    </body>
    </html>
    

     

    这里就可以通过实例化的对象publisher_form来显示,这里不需要再单独对应name、city、address等属性字段了,另外通过publisher_form对象显示的方式有多种,比如as_p、as_table、as_ul。这里用as_p为例,刷新页面

    进一步查看源代码:

    发现都是用p标签来进行分界各个字段属性,另外通过id来标识区分各个字段的名称,比如id=id_name,id=id_address等,name的值则等于views.py从forms.py中定义的对应名称值。

     接下来解决提交时验证的问题,代码如下:

    def add_publisher(request):
        if request.method == "POST":
             # 使用django Form表单提交
              publisher_form = PublisherForm(request.POST)#通过request.POST传过来的数据将表单PublisherForm初始化以后再赋给publisher_form生成一个带有提交对象的表单
              if publisher_form.is_valid():#对提交过来的对象内容进行验证
                  Publisher.objects.create(
                      name= publisher_form.cleaned_data['name'],
                      address = publisher_form.cleaned_data['address'],
                      city = publisher_form.cleaned_data['city'],
                      state_province = publisher_form.cleaned_data['state_province'],
                      website = publisher_form.cleaned_data['website'],
                  )
                  return HttpResponse("添加信息成功")
    
        else:
              publisher_form = PublisherForm() #定义一个实例来接收初始化的PublisherForm类
        return render(request,'add_publisher.html',locals())
    

      刷新请求页面如下所示:

    点击提交出现如下页面:

     说明字段内容为必须填写,为空字段是不允许提交。填写相关信息继续提交:

    点击添加:

    提示网址不符合规范。修改后继续提交:

    再添加:

     

    查看数据库:

    这样就添加成功提交数据。

    通过这个form类,虽然增加了一个form.py文件,但是从整体上看代码是简化了,不用去一个一个的写字段规范验证方法,同时模板里也相对以前原生html要简化很多,又提高了代码 的可读性

     对于界面友好度,默认显示如下:

    我们可以通过一个中文显示标签(label)来定义,具体实现在forms,py中添加:

    from django import forms
    
    class PublisherForm(forms.Form):
            name = forms.CharField(label='名称')
            address = forms.CharField(label='地址')
            city = forms.CharField(label='城市')
            state_province = forms.CharField(label='省份')
            country = forms.CharField(label='国家')
            website = forms.URLField(label='网址')
    

     刷新页面:

    提交数据不符合规范时的提示信息“This field is required.” 也可以修改:

    同样在forms.py中每个字段实例化时都有一个错误信息的属性:error_messages,这里我们可以根据实际情况对该属性的值进行重新定义

    from django import forms
    
    class PublisherForm(forms.Form):
            name = forms.CharField(label='名称',error_messages={"required":"该项为必填项"})
            address = forms.CharField(label='地址',error_messages={"required":"该项为必填项"})
            city = forms.CharField(label='城市',error_messages={"required":"该项为必填项"})
            state_province = forms.CharField(label='省份',error_messages={"required":"该项为必填项"})
            country = forms.CharField(label='国家',error_messages={"required":"该项为必填项"})
            website = forms.URLField(label='网址',error_messages={"required":"该项为必填项"})
    

      

    刷新页面:

    也可以对相应字段长度进行定义,如果超出了就提示对应的信息。比如对名称长度定义为100,超出长度则提示"名称太长"

    from django import forms
    
    class PublisherForm(forms.Form):
            name = forms.CharField(label='名称',max_length=100,error_messages={"required":"名称太长不符合规范"})
            address = forms.CharField(label='地址',error_messages={"required":"该项为必填项"})
            city = forms.CharField(label='城市',error_messages={"required":"该项为必填项"})
            state_province = forms.CharField(label='省份',error_messages={"required":"该项为必填项"})
            country = forms.CharField(label='国家',error_messages={"required":"该项为必填项"})
            website = forms.URLField(label='网址',error_messages={"required":"该项为必填项"})
    

      

     


    四、使用ModelForm的情况

    使用ModelForm时在定义PublisherForm时候直接继承它,实现代码如下:

    forms.py

    from django import forms
    from hello.models import Publisher
    class PublisherForm(forms.ModelForm):
       
            class Meta:
                model = Publisher
                exclude = ("id",)
    

      

    views.py

    def add_publisher(request):
    if request.method == "POST":

    #使用ModelForm情况
    publisher_form = PublisherForm(request.POST)
    if publisher_form.is_valid():
    publisher_form.save()#插入数据操作语句
    return HttpResponse("添加信息成功")

    else:
    publisher_form = PublisherForm() # 定义一个实例来接收初始化的PublisherForm类
    return render(request, 'add_publisher.html', locals())

      

    刷新页面:

    添加提交内容:

    提交结果:

     查看数据库添加的数据:

    总结:
    使用Django中的Form可以大大简化代码,常用的表单功能特性都整合到了Form中,而ModelForm可以和Model进行绑定,更进一步简化操作

    查看forms相关资料:
    https://docs.djangoproject.com/en/1.9/ref/forms/api/
    https://docs.djangoproject.com/en/1.9/ref/forms/fields/

    五、Form表单的验证方法

    1、表单字段的验证器

    https://docs.djangoproject.com/en/1.9/ref/validators/

    forms.py代码实现如下:

    from django import forms
    from hello.models import Publisher
    from django.core.exceptions import ValidationError
    
    #表单字段的验证器
    def validate_name(value):
        try:
            Publisher.objects.get(name=value)
            raise ValidationError("%s的信息已经存在"% value)
        except Publisher.DoesNotExist:
            pass
    class PublisherForm(forms.ModelForm):
            
            name = forms.CharField(label="名称",validators=[validate_name])
            class Meta:
                model = Publisher
                exclude = ("id",)

    class PublisherForm(forms.ModelForm):
          name = forms.CharField(label="名称",validators=[validate_name])
    class Meta:
    model = Publisher
    exclude = ("id",)

     操作演示:

    以name=“南京大学出版社”为例

     提交信息中名称"南京大学出版社"

    2、clean_filedname,验证字段,针对某个字段进行验证

    forms.py代码实现方式:

    from django import forms
    from hello.models import Publisher
    from django.core.exceptions import ValidationError
    
    
            def clean_name(self):
                value = self.cleaned_data.get('name')#表单对象self自己通过cleand_data属性调用get方法获取name的值然后赋给value
                try:
                    Publisher.objects.get(name=value)#将上面的value值通过Publisher.objects.get进行判断
                    raise ValidationError("%s的信息已经存在" % value)
                except Publisher.DoesNotExist:
                    pass
                return value #在没有出错的情况下将原有的值返回回去,否则表单无法获取值
            class Meta:
                model = Publisher
                exclude = ("id",)
    

     同样以"name=南京大学出版社"为例

    3、表单clean方法,可针对整个表单进行验证

     forms.py实现代码:

    from django import forms
    from hello.models import Publisher
    from django.core.exceptions import ValidationError
    
            #通过clean对整个表单进行验证
            def clean(self):
                cleaned_data = super(PublisherForm,self).clean()#获取父类中的方法clean()
                value = cleaned_data.get('name')
                try:
                   Publisher.objects.get(name=value)
                   self._errors['name']=self.error_class(["%s的信息已经存在"%value])#指定不能重复的字段名称
                except Publisher.DoesNotExist:
                    pass
                return cleaned_data #返回整个表单的值
    
            class Meta:
                model = Publisher
                exclude = ("id",)
    

      提交空内容:

    同样以name=南京大学出版社为例

     注释:代码中指定了对name字段就行验证,所以name值存在了就提示内容已经存在。

  • 相关阅读:
    [考试]20150811
    [考试]20150810
    [随笔]暑假过了,暑假来了
    [考试]20150808
    动态规划大合集II
    [知识点][旧版]C++中的运算符
    NOIP动态规划大合集
    [考试]20150729
    [考试]20150728
    /=============分隔线=============/
  • 原文地址:https://www.cnblogs.com/kindnull/p/8379804.html
Copyright © 2011-2022 走看看