zoukankan      html  css  js  c++  java
  • 【Django】:ModelForm操作

    ModelForm

    内容回顾:

    Model
        - 数据库操作
        - 验证
        class A(MOdel):
            user =
            email =
            pwd =
    Form
        class LoginForm(Form):
            email = fields.EmailField()
            user =
            pwd =
        - is_valid -> 每一个字段进行正则(字段内置正则) + clean_字段 -> clean(__all__)  -> _post_clean
        - cleand_data
        - error
        --------> 推荐 <---------
    
    1、Model操作
    
    创建数据表
    操作数据库表
    数据验证(弱)
    2、Form操作
    
    数据验证(强大)
    3、ModelForm
    
    数据库操作
    数据验证
    适合小程序,特别方便
    自定制
    缺点:ModelForm的耦合性非常强,数据库操作和验证操作代码都放到一块,项目大了的话,代码无法分离;建议以后写程序Model和Form分开写
    
     
    内容回顾

    1、ModelForm简单验证

    其他文件:

    from django.db import models
    
    # Create your models here.
    
    class UserInfo(models.Model):
        # verbose_name 等同于Form类里面的label
        username = models.CharField(verbose_name='用户',max_length=32)
        email = models.EmailField(verbose_name='邮件')
        user_type = models.ForeignKey(verbose_name='类型',to='UserType',to_field='id')
    
    
    class UserType(models.Model):
        caption = models.CharField(max_length=32)
    
        def __str__(self):          #打印名称,不写显示的是obj对象
            return self.caption
    models.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/index/" method="post">
            {% csrf_token %}
            {{ obj.as_p }}
            <input type="submit" value="提交"/>
        </form>
    
    </body>
    </html>
    index.html

    ModelForm文件:

    from django import forms
    from django.forms import fields
    from app import models
    
    class UserInfoModelForm(forms.ModelForm):
        class Meta:
            model = models.UserInfo     #去UserInfo类中获取数据
            fields = '__all__'        #__all__ 代指所有字段
            # fields = ['username','email']       #指定显示的字段
            # exclude = ['username']      #不显示的字段

    处理文件:

    from django.shortcuts import render
    def index(request):
        if request.method == 'GET':
            obj = UserInfoModelForm()
            return render(request,'index.html',{'obj':obj})
        elif request.method == 'POST':
            obj = UserInfoModelForm(request.POST)
            result = obj.is_valid()
            if result:
                print(obj.cleaned_data)             #如果models里没有__str__方法,则user_type获取
                                                            #到的是一个对象,可直接根据对象进行操作
                print(obj.cleaned_data['user_type'])
                # {'username': 'James', 'user_type': < UserType: 超级用户 >, 'email': 'ffd@fdsf.com'}
                # 超级用户
            else:
                print(obj.errors)
            return render(request,'index.html',{'obj':obj})

    注:ModelForm最终继承了BaseForm,BaseForm里面具有is_valid方法,所以ModelForm也可以用is_valid进行验证

    2、ModelForm组件

    ModelForm
        a.  class Meta:
                model,                           # 对应Model的
                fields=None,                     # 字段
                exclude=None,                    # 排除字段 
                labels=None,                     # 提示信息  labels ={'username':'用户名'}可写多个
                help_texts=None,                 # 帮助提示信息    help_texts = {'username':'help info'}
                widgets=None,                    # 自定义插件
                error_messages=None,             # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)
                field_classes=None               # 自定义字段类 (也可以自定义字段)
                localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据
                如:
                    数据库中
                        2016-12-27 04:10:57
                    setting中的配置
                        TIME_ZONE = 'Asia/Shanghai'
                        USE_TZ = True
                    则显示:
                        2016-12-27 12:10:57
        b. 验证执行过程
            is_valid -> full_clean -> 钩子 -> 整体错误
     
        c. 字典字段验证
            def clean_字段名(self):
                # 可以抛出异常
                # from django.core.exceptions import ValidationError
                return "新值"
        d. 用于验证
            model_form_obj = XXOOModelForm()
            model_form_obj.is_valid()
            model_form_obj.errors.as_json()
            model_form_obj.clean()
            model_form_obj.cleaned_data
        e. 用于创建
            model_form_obj = XXOOModelForm(request.POST)
            #### 页面显示,并提交 #####
            # 默认保存多对多
                obj = form.save(commit=True)
            # 不做任何操作,内部定义 save_m2m(用于保存多对多)
                obj = form.save(commit=False)
                obj.save()      # 保存单表信息
                obj.save_m2m()  # 保存关联多对多信息
     
        f. 用于更新和初始化
            obj = model.tb.objects.get(id=1)
            model_form_obj = XXOOModelForm(request.POST,instance=obj)
            ...
     
            PS: 单纯初始化
                model_form_obj = XXOOModelForm(initial={...})
    ModelForm所有组件

     自定义插件widgets:

    from django.forms import widgets as Fwidgets    #避免跟widgets重名
    class UserInfoModelForm(forms.ModelForm):
        class Meta:
            model = models.UserInfo     #去UserInfo类中获取数据
            fields = '__all__'        #__all__ 代指所有字段
            labels ={'username':'用户名'}
            help_texts = {'username':'...'}
            widgets = {
                'username':Fwidgets.Textarea(attrs={'class':'c1'})
            }
    

    错误信息error_messages:

    from django.forms import widgets as Fwidgets    #避免跟widgets重名
    class UserInfoModelForm(forms.ModelForm):
        class Meta:
            ---snip---
            error_messages = {
                '__all__':{},       #整体的错误信息
                'email':{'required':'邮箱不能为空'}
            }
    

     自定义更改字段验证规则field_classes:

    from django.forms import fields as Ffields     #避免跟fields重名
    class UserInfoModelForm(forms.ModelForm):
        class Meta:
            ---snip---
            field_classes ={
                'email':Ffields.URLField    #把邮件格式改为url格式验证
            }
    

    3、 ModelForm创建数据

    其他文件:

    from django.db import models
    
    # Create your models here.
    
    class UserInfo(models.Model):
        # verbose_name 等同于Form类里面的label
        username = models.CharField(verbose_name='用户',max_length=32)
        email = models.EmailField(verbose_name='邮件')
        user_type = models.ForeignKey(verbose_name='类型',to='UserType',to_field='id')
        user_group = models.ManyToManyField('UserGroup')
    
    class UserType(models.Model):
        caption = models.CharField(max_length=32)
    
        def __str__(self):          #打印名称,不写显示的是obj对象
            return self.caption
    
    class UserGroup(models.Model):
        groupname = models.CharField(max_length=32)
    
        def __str__(self):          #打印名称,不写显示的是obj对象
            return self.groupname
    models.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/index/" method="post">
            {% csrf_token %}
            {{ obj.as_p }}
            <input type="submit" value="提交"/>
        </form>
    
    </body>
    </html>
    index.html
    from django import forms
    from app import models
    from django.forms import widgets as Fwidgets    #避免跟widgets重名
    from django.forms import fields as Ffields     #避免跟fields重名
    class UserInfoModelForm(forms.ModelForm):
        class Meta:
            model = models.UserInfo     #去UserInfo类中获取数据
            fields = '__all__'        #__all__ 代指所有字段
            labels ={'username':'用户名'}
            help_texts = {'username':'...'}
            widgets = {
                'username':Fwidgets.Textarea(attrs={'class':'c1'})
            }
            error_messages = {
                '__all__':{},       #整体的错误信息
                'email':{'required':'邮箱不能为空'}
            }
    ModelForm验证

    处理文件:

    from django.shortcuts import render
    def index(request):
        if request.method == 'GET':
            obj = UserInfoModelForm()
            return render(request,'index.html',{'obj':obj})
        elif request.method == 'POST':
            obj = UserInfoModelForm(request.POST)
            if obj.is_valid():
                # 验证成功直接保存
                obj.save()         #默认commit=True,会保存多对多
                # 保存一对多表单
                # instance = obj.save(commit=False)
                # instance.save()
                # 保存多对多数据
                # obj.save_m2m()
            return render(request,'index.html',{'obj':obj})
    

    4、ModelForm更新和初始化  

    描述:打开用户列表,显示用户信息,点击编辑跳转到编辑页面,Input显示选择用户的当前值;提交后,对数据进行更新

    其他文件:

    from django.conf.urls import url
    from django.contrib import admin
    from app import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/$', views.index),
        url(r'^list/$', views.user_list),
        url(r'^edit-(d+)', views.user_edit),
    ]
    urls.py
    from django.db import models
    
    # Create your models here.
    
    class UserInfo(models.Model):
        # verbose_name 等同于Form类里面的label
        username = models.CharField(verbose_name='用户',max_length=32)
        email = models.EmailField(verbose_name='邮件')
        user_type = models.ForeignKey(verbose_name='类型',to='UserType',to_field='id')
        user_group = models.ManyToManyField('UserGroup')
    
    class UserType(models.Model):
        caption = models.CharField(max_length=32)
    
        def __str__(self):          #打印名称,不写显示的是obj对象
            return self.caption
    
    class UserGroup(models.Model):
        groupname = models.CharField(max_length=32)
    
        def __str__(self):          #打印名称,不写显示的是obj对象
            return self.groupname
    models.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <ul>
            {% for row in list %}
                <p>{{ row.username }}--{{ row.user_type.caption }}--<a href="/edit-{{ row.id }}">编辑</a></p>
            {% endfor %}
        </ul>
    </body>
    </html>
    user_list.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/edit-{{ nid }}" method="post">
            {% csrf_token %}
            {{ obj.as_p }}
            <input type="submit" value="提交" />
        </form>
    
    </body>
    </html>
    user_edit.html

    处理文件:

    from django.shortcuts import render
    from django import forms
    from app import models
    
    class UserInfoModelForm(forms.ModelForm):
        class Meta:
            model = models.UserInfo     #去UserInfo类中获取数据
            fields = '__all__'        #__all__ 代指所有字段
            labels ={'username':'用户名'}
            help_texts = {'username':'...'}
    
    def user_list(request):
        if request.method == 'GET':
            list = models.UserInfo.objects.all().select_related('user_type')
            return render(request,'user_list.html',{'list':list})
    
    def user_edit(request,nid):
        if request.method == 'GET':
            user_obj = models.UserInfo.objects.filter(id=nid).first()
            obj = UserInfoModelForm(instance=user_obj)    # instance显示user_obj的对应值
            return render(request, 'user_eidt.html', {'obj': obj,'nid':nid})
        elif request.method == 'POST':
            user_obj = models.UserInfo.objects.filter(id=nid).first()
            obj = UserInfoModelForm(request.POST,instance=user_obj)     #instance更新user_obj而不是添加
            if obj.is_valid():
                # 验证成功直接更新
                obj.save()
            else:
                print(obj.errors.as_json())
            return render(request, 'user_eidt.html', {'obj': obj,'nid':nid})
    

      

    5、ModelForm钩子

    ModelForm继承了is_valid方法,所以跟Form里的钩子用法一毛一样

    class UserInfoModelForm(forms.ModelForm):
    
        class Meta:
            ---snip---
            def clean_username(self):
          pass
    

    生成额外的标签:

    class UserInfoModelForm(forms.ModelForm):
        # 生成额外的标签 选择框
        is_rmb = fields.CharField(widget=Fwidgets.CheckboxInput())
        class Meta:
                ---snip---
    

      

      

     

    《第二十四章》

  • 相关阅读:
    【转】Geary's C
    ArcGIS中影像与影像,影像与点云之间的配准
    [转] EPSG CODE的含义
    地图投影
    【从翻译mos文章】oracle linux 和外部存储系统 关系
    找呀志_使用SQLiteDatabase增删改提供的搜索方法和事务
    [049] 微信公众平台视频公开课1说话-基础知识
    我看到西电通院考试——学生应该做的事情?
    使用 Eclipse 的 SVN 主要插件创建项目/支/标签
    【SSH三个框架】Hibernate第十篇基础:inverse属性具体解释
  • 原文地址:https://www.cnblogs.com/lianzhilei/p/6390687.html
Copyright © 2011-2022 走看看