zoukankan      html  css  js  c++  java
  • Django之ModelForm

     顾名思义,Model + Form == ModelForm。model和form的合体,所以有以下功能:

    • 验证数据字段(Form的功能)
    • 数据库操作(Model的功能)

    model有操作数据库的字段,form验证也有那几个字段,虽然耦合度降低,但是代码是有重复的。如果利用model里的字段,那是不是form里的字段就不用写了。

    在了解ModelForm模块之前,我们来看看Model+Form原生写法以及Model+Form模块,最后来看看三者的区别及优势。

    一、Model+Form(原生写法)

    1、models.py文件

    class UserType(models.Model):
        caption = models.CharField(max_length=32)
    
    class User(models.Model):
        username = models.CharField(max_length=32)
        email = models.EmailField(max_length=32)
        #指定关系一对多,指定和哪张表建立一对多,指定和哪个字段关联        
        user_type = models.ForeignKey(to='UserType',to_field='id')
    

      


    2、前端myform.py文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
         <form action="/myform/" method="POST">
            {% csrf_token %}
            {{ msg }}<br/>
             <label for="id_username">Username:</label>
             <input type="text" id="id_username" name="username"/>
             <br/>
             <label for="id_email">Email:</label>
             <input type="text" id="id_email" name="email"/>
             <br/>
             <select name="user_type">
                 {% for t in user_type %}
                  <option name ="{{ t.caption }}">{{ t.caption }}</option>
                 {% endfor %}
            </select>
    
             <input type="submit" value="提交">
        </form>
        <br/>
       <table>
           <th>
               <tr>用户名</tr>
               <tr>邮箱</tr>
               <tr>角色</tr>
           </th>
           {% for obj in new_obj %}
           <tr>
               <td>{{ obj.username }}</td>
               <td>{{ obj.email }}</td>
               <td>{{ obj.user_type.caption }}</td>
           </tr>
            {% endfor %}
       </table>
    </body>
    </html>
    

      

    3、views.py文件

    def myform(request):
        if request.method == 'GET':
            obj = models.User.objects.all()
            user_type = models.UserType.objects.all()
            return render(request,'myform.html',{'new_obj':obj,'user_type':user_type})
        elif request.method == 'POST':
            msg = ''
            username = request.POST.get('username')
            email = request.POST.get('email')
            u_type = request.POST.get('user_type')
    
            user_type = models.UserType.objects.all()
            obj = models.User.objects.all()
            c = models.User.objects.filter(username=username, email=email).count()
            ut  = models.UserType.objects.filter(caption=u_type).first()
    
            if c>0:
                msg = '用户名和邮箱重复!'
                return render(request, 'myform.html', {'obj': obj,'msg':msg,'user_type':user_type})
            elif not username or not email:
                msg = '用户名和邮箱不能为空!'
                return render(request, 'myform.html', {'obj': obj, 'msg':msg,'user_type':user_type})
            else:
                msg = '增加记录成功!'
                models.User.objects.create(username=username, email=email, user_type=ut)
                return render(request, 'myform.html', {'obj': obj,'msg':msg,'user_type':user_type})
    

      

    4、效果图

     

     

     

    二、Model+Form模块

    1、models.py文件

    同上面的models.py文件

     

    2、forms.py文件

    #coding:utf-8
    from django import forms
    from django.forms import fields
    from app01 import models
    from django.core.exceptions import ValidationError
    
    class UserInfoForm(forms.Form):
        username = fields.CharField(max_length=32)
        email = fields.EmailField(max_length=32)
        user_type = fields.ChoiceField(
            choices=models.UserType.objects.values_list('id','caption')
        )
    
        # 下面的操作是让数据在网页上实时更新:每次刷新时,必先执行父类的初始化函数,再设定下拉列表框选项。
        def __init__(self, *args, **kwargs):
            super(UserInfoForm,self).__init__(*args, **kwargs)
            self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption')
    
      #自定义清理数据字段操作:1、清理单个字段;2、清理多个字段;
        # def clean_username(self):
        #     #
        #     value = self.cleaned_data['username']
        #     if value == 'root':
        #         return value
        #     else:
        #         raise ValidationError('你不是我的...')
    
        # def clean(self):
        #     username = self.cleaned_data.get('username')
        #     email = self.cleaned_data.get('email')
        #     if models.User.objects.filter(username=username, email=email).count() == 1:
        #         raise ValidationError('用户名和邮箱联合唯一索引重复!!!')
        #     return self.cleaned_data
    
        #
        # def _post_clean(self):
        #     print 'aaa %s' %self.cleaned_data
        #     username = self.cleaned_data['username']
        #     email = self.cleaned_data['email']
        #     if models.User.objects.filter(username=username,email=email).count()==1:
        #         self.add_error("__all__", ValidationError('用户名和邮箱联合唯一索引重复!!!'))
    

      

      

    3、前端文件index.html

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/index/" method="POST" novalidate="novalidate">
            {% csrf_token %}
         #作为p标签展示,obj.as_table将内容渲染在tr中;obj.as_p,将内容渲染在p标签中;obj.as_ul将内容渲染在li标签中。
            {{ obj.as_p }}
            <input type="submit" value="提交">
        </form>
    
    
     <table>
           <th>
               <tr>用户名</tr>
               <tr>邮箱</tr>
               <tr>角色</tr>
           </th>
           {% for obj in new_obj %}
           <tr>
               <td>{{ obj.username }}</td>
               <td>{{ obj.email }}</td>
               <td>{{ obj.user_type.caption }}</td>
           </tr>
            {% endfor %}
       </table>
    </body>
    </html>
    

      

    4、views.py文件

    # -*- coding: utf-8 -*-
    from __future__ import unicode_literals
    
    from django.shortcuts import render,HttpResponse
    from app01 import models
    from forms import UserInfoForm
    # Create your views here.
    
    
    def index(request):
        if request.method == 'GET':
            obj = UserInfoForm()
            new_obj = models.User.objects.all()
            return render(request,'index.html',{'obj':obj,'new_obj':new_obj})
        elif request.method == 'POST':
            obj = UserInfoForm(request.POST)
            if obj.is_valid():
                rt_dic = obj.cleaned_data
                username = rt_dic.get('username')
                email = rt_dic.get('email')
                user_type_id = rt_dic.get('user_type')
                ut = models.UserType.objects.filter(id=user_type_id).first()
                models.User.objects.create(username=username,email=email,user_type=ut)
            return render(request,'index.html',{'obj':obj})
    

      

    5、效果

     POST提交数据:

     GET方式:

     

    三、ModelForm模块

    1、models.py文件

    同上面的models.py文件

    2、forms.py文件

     

    class UserModelForm(forms.ModelForm):
        class Meta:
            #指定model的哪个表
            model = models.User
            #指定model的那些字段
            fields = "__all__"
    

      

    3、前端文件index.html

     

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/mf/" method="POST">
            {% csrf_token %}
            {{ obj.as_p }}
            <input type="submit" value="提交">
        </form>
     <table>
           <th>
               <tr>用户名</tr>
               <tr>邮箱</tr>
               <tr>角色</tr>
           </th>
           {% for obj in new_obj %}
           <tr>
               <td>{{ obj.username }}</td>
               <td>{{ obj.email }}</td>
               <td>{{ obj.user_type.caption }}</td>
           </tr>
            {% endfor %}
       </table>
    </body>
    </html>
    

      

     4、views.py文件

    # -*- coding: utf-8 -*-
    from __future__ import unicode_literals
    
    from django.shortcuts import render,HttpResponse
    from app01 import models
    from forms import UserInfoForm
    from django import forms
    
    # Create your views here.
    
    def mf(request):
        if request.method == 'GET':
            obj = UserModelForm()
            new_obj = models.User.objects.all()
            return render(request,'index.html',{'obj':obj,'new_obj':new_obj})
        elif request.method == 'POST':
            obj = UserModelForm(request.POST)
            if obj.is_valid():
                obj.save()
            return render(request,'index.html',{'obj':obj})
    

      

    5、效果

     

     

    四、三种方式比较

    共同点:

    • models.py,即数据库字段的定义都是一样。

    不同点:

    1、Model+原生Form

    • HTML里面的form表单字段需要用户自己写
    • 表单里面字段的格式错误需要用户自己判断,考虑的情况比较多【必选】
    • 保存方式为create()

    2、Model+Form模块

    • 需要用户定义forms(表单字段以及字段验证方法【可选】)
    • HTML里面的form表单字段不需要用户写,直接使用obj.as_p就行
    • 保存方式为create()
    • 继承方式:UserForm -> Form -> BaseForm

    3、纯ModelForm模块

    • 继承ModelForm,不需要自定义forms文件
    • 直接可以指定models的对象以及对象的字段
    • HTML里面的form表单字段不需要用户写,直接使用obj.as_p就行
    • 保存方式为save()
    • 继承方式:UserModelForm (ModelForm名称)-> ModelForm -> BaseModelForm【里面会有save方法】 -> BaseForm
    • is_valid()  ===>full_clean()=====>【self._clean_fields() 清洗单个字段     self._clean_form()清洗整个表单,调用clean()方法,自定义错误的钩子       self._post_clean()用户自定义错误的钩子】
  • 相关阅读:
    gitlab 启用HTTPS
    centos7 部署 汉化版 gitlab 10.0.2
    前端常见跨域解决方案(全)
    [转]用python爬虫抓站的一些技巧总结 zz
    【转】通用权限管理设计 之 数据权限
    【转】通用权限管理设计 之 功能权限设计
    JavaScript数据结构和算法
    Vue.js 插件开发详解
    wdcpV3面板安装ssl证书 apache教程 子站SSL配置
    [POJ-2823] -Sliding Window
  • 原文地址:https://www.cnblogs.com/skyflask/p/9710809.html
Copyright © 2011-2022 走看看