33.Django ModelForm

ModelForm

 1.ModeForm简单验证

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

views.py

from django.shortcuts import render,redirect
from app01 import models
from django import forms
from django.forms import fields

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

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所有组件

(1)自定义插件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'})
        }

(2)错误信息error_message

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

(3)自定义更改字段验证规则field_classses

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


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': '邮箱不能为空'}
        }
        field_classes = {
            'email': Ffields.URLField  # 把邮件格式改为url格式验证
        }

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})

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
<!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>
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 app01 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),
]
from django.db import models


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

user_list.html

<!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_edit.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>

views.py

from django.shortcuts import render,redirect
from app01 import models
from django import forms
from django.forms import fields
from django.forms import widgets as Fwidgets
from django.forms import fields as Ffields


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': '邮箱不能为空'}
        }

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})


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_edit.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_edit.html', {'obj': obj, 'nid': nid})

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小李刀刀的专栏

[译]Laravel 5.0 之方法注入

本文译自 Matt Stauffer 的系列文章. ---- Laravel 5.0 中, 容器可以对其解析的方法进行自动分析, 然后根据类型限制把方法所需要的...

35660
来自专栏Linux驱动

QT-第一个程序 Hello QT , 以及QT creator介绍

第一个程序 - Hello QT 首先写main.cpp: #include <QApplication> #include <QMainWindow> #in...

42770
来自专栏owent

可执行文件压缩

最近看Rust相关东西的时候看到一篇关于压缩可执行文件的文章。压缩可执行文件对嵌入式开发特别有用,但是延伸一下用来减少我们游戏行业里预编译的工具二进制包大小和A...

54110
来自专栏社区的朋友们

深入浅出 Nodejs( 三 ):Nodejs 核心模块机制

本篇教程关于Nodejs的核心模块机制,具体讲Nodejs核心模块的原理、C/C++扩展模块的原理、包、模块调用栈以及NPM。

1.2K00
来自专栏Android 研究

Android插件化基础3----Android的编译打包流程详解

.apk文件其实就是一个压缩包,把文件的后缀改成.zip,用压缩软件解压搜就可的下图(我是mac)

30220
来自专栏JackeyGao的博客

Celery用户手册 - Tasks

Tasks是Celery 应用的构建块。事实上Celery应用是由一个或多个Task拼装组成的。

24830
来自专栏佳爷的后花媛

php基础(一)

static 是静态变量,在局部函数中存在且只初始化一次,使用过后再次使用会使用上次执行的结果; 作为计数,程序内部缓存,单例模式中都有用到。

29220
来自专栏JadePeng的技术博客

axios介绍与使用说明 axios中文文档

本周在做一个使用vuejs的前端项目,访问后端服务使用axios库,这里对照官方文档,简单记录下,也方便大家参考。 Axios 是一个基于 Promise 的 ...

3.1K90
来自专栏Google Dart

微信小程序之支付详解(填坑) 原

首先,你采用什么语言选择对应的sdk,记住:微信sdk默认签名是HMACSHA256,因为小程序只支持MD5,故你这里即使获取了prepay_id,在小程序发起...

14530
来自专栏YoungGy

R包简单教程

R包,类似C、Python中库的概念,指包含特定领域的函数、数据、文档等的集合。通过调用包,可以直接使用包中现成的数据、函数等,使开发方便快捷高效。

363100

扫码关注云+社区

领取腾讯云代金券