django-Modelform
简介
Model + Form ==> ModelForm。model和form的结合体,所以有以下功能:
- 验证
- 数据库操作
Form回顾
models.py
1
2
3
4
5
6
7
|
class UserType(models.Model):
caption = models.CharField(max_length = 32 )
class UserInfo(models.Model):
username = models.CharField(max_length = 32 )
email = models.EmailField()
user_type = models.ForeignKey(to = 'UserType' ,to_field = 'id' )
|
forms.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
from django import forms
from django.forms import fields
class UserInfoForm(forms.Form):
# username = models.CharField(max_length=32) <-- models
username = fields.CharField(max_length = 32 )
# email = models.EmailField() <-- models
email = fields.EmailField()
# user_type = models.ForeignKey(to='UserType',to_field='id') <-- models
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' )
|
index.html
1
2
3
4
5
6
7
|
<body>
<form action = "/index/" method = "POST" novalidate = "novalidate" >
{ % csrf_token % }
{{ obj.as_p }}
< input type = "submit" value = "提交" >
< / form>
< / body>
|
从上面的小例子能看出,models的字段和forms的字段大部分都是重复的,所以,django给我们提供了一种更为简洁的ModelFrom
ModelFormde 的使用
首先导入ModelForm
from django.forms import ModelForm
在视图函数中,定义一个类,比如就叫StudentList,这个类要继承ModelForm,在这个类中再写一个原类Meta(规定写法,并注意首字母是大写的)
在这个原类中,有以下属性(部分):
class StudentList(ModelForm):class Meta:model = models.Student #对应的Model中的类fields = "__all__" #字段,如果是__all__,就是表示列出所有的字段exclude = None #排除的字段labels = None #提示信息help_texts = None #帮助提示信息widgets = None #自定义插件error_messages = None #自定义错误信息
#error_messages用法:error_messages = {'name':{'required':"用户名不能为空",},'age':{'required':"年龄不能为空",},}#widgets用法,比如把输入用户名的input框给为Textarea
#首先得导入模块from django.forms import widgets as wid #因为重名,所以起个别名widgets = {"name":wid.Textarea(attrs={"class":"c1"}) #还可以自定义属性}
#labels,自定义在前端显示的名字labels= {"name":"用户名"}
如果想增加一个字段,就在class Meta 之前写这个字段。然后在url对应的视图函数中实例化这个类,把这个对象传给前端。
然后前端只需要 {{ student_list.as_p }} 一下,所有的字段就都出来了,可以用as_p显示全部,也可以通过for循环这student_list,拿到的是一个个input框,现在我们就不用as_p,手动把这些input框搞出来,as_p拿到的页面太丑。
首先 for循环这个student_list,拿到student对象,直接在前端打印这个student,是个input框;student.label ,拿到数据库中每个字段的verbose_name ,如果没有设置这个属性,拿到的默认就是字段名;还可以通过student.errors.0 拿到错误信息,还有student.field,是拿到每个字段,如果这个字段是多对多字段,还能stuent.field.queryset,拿到所有关联的字段,还能stuent.field.queryset.model,拿到所有关联的字段的类。有了这些,我们就可以通过bootstrap,自己拼出来想要的样式了
比如:
<body><div class="container" ><h1>student</h1><form method="POST" novalidate>{% csrf_token %}
{# {{ student_list.as_p }}#}{% for student in student_list %}<div class="form-group col-md-6">{# 拿到数据字段的verbose_name,没有就默认显示字段名 #}<label class="col-md-3 control-label">{{ student.label }}</label><div class="col-md-9" style="position: relative;">{{ student }}</div></div>{% endfor %}<div class="col-md-2 col-md-offset-10"><input type="submit" value="提交" class="btn-primary"></div></form></div>
</body>
现在还缺一个input框的form-control样式,可以考虑在后台的widget里面添加。比如这样:from django.forms import widgets as wid #因为重名,所以起个别名widgets = {"name":wid.TextInput(attrs={'class':'form-control'}),"age":wid.NumberInput(attrs={'class':'form-control'}),"email":wid.EmailInput(attrs={'class':'form-control'})}
当然也可以在js中,找到所有的input框,加上这个样式,也行。
保存数据的时候,不用挨个取数据了,只需要save一下。
def student(request):if request.method == 'GET':student_list = StudentList()return render(request,'student.html',{'student_list':student_list})else:student_list = StudentList(request.POST)if student_list.is_valid():student_list.save()return redirect(request,'student_list.html',{'student_list':student_list})
编辑数据:
如果不用ModelForm,编辑的时候得显示之前的数据吧,还得挨个取一遍值,如果ModelForm,只需要加一个instance=obj(obj是要修改的数据库的一条数据的对象)就可以得到同样的效果。
保存的时候要注意,一定要注意有这个对象(instance=obj),否则不知道更新哪一个数据。
代码示例:
from django.shortcuts import render,HttpResponse,redirect
from django.forms import ModelForm
# Create your views here.
from app01 import modelsdef test(request):# model_form = models.Studentmodel_form = models.Student.objects.all()return render(request,'test.html',{'model_form':model_form})class StudentList(ModelForm):class Meta:model = models.Student #对应的Model中的类fields = "__all__" #字段,如果是__all__,就是表示列出所有的字段exclude = None #排除的字段labels = None #提示信息help_texts = None #帮助提示信息widgets = None #自定义插件error_messages = None #自定义错误信息
#error_messages用法:error_messages = {'name':{'required':"用户名不能为空",},'age':{'required':"年龄不能为空",},}#widgets用法,比如把输入用户名的input框给为Textarea
#首先得导入模块from django.forms import widgets as wid #因为重名,所以起个别名widgets = {"name":wid.Textarea}
#labels,自定义在前端显示的名字labels= {"name":"用户名"}
def student(request):if request.method == 'GET':student_list = StudentList()return render(request,'student.html',{'student_list':student_list})else:student_list = StudentList(request.POST)if student_list.is_valid():student_list.save()return render(request,'student.html',{'student_list':student_list})def student_edit(request,pk):obj = models.Student.objects.filter(pk=pk).first()if not obj:return redirect('test')if request.method == "GET":student_list = StudentList(instance=obj)return render(request,'student_edit.html',{'student_list':student_list})else:student_list = StudentList(request.POST,instance=obj)if student_list.is_valid():student_list.save()return render(request,'student_edit.html',{'student_list':student_list})使用ModelForm编辑数据
对于验证规则,很多浏览器都比较智能,会自动帮我们做一些验证,可以在form表单上加 novalidate 属性就可以不让浏览器为我们做验证
ModelForm还支持所有form的功能,比如钩子,所以我们就可以通过钩子来自定义验证规则
写法和forms的写法一样:
class AuthorForm(forms.ModelForm):class Meta:model = Authorfields = ('name', 'title')def clean_name(self):if ...return self.clean_data['name']else:raise ValidationError(‘sdgsadga’)...
ModelForm的用法
forms.py
1
2
3
4
5
|
class UserInfoModelForm(forms.ModelForm):
class Meta:
model = models.UserInfo # 与models建立了依赖关系
fields = "__all__"
|
views.py
1
2
3
4
5
6
7
8
9
10
|
def index(request):
if request.method = = "GET" :
obj = UserInfoModelForm()
return render(request, "index.html" ,{ 'obj' :obj})
elif request.method = = "POST" :
obj = UserInfoModelForm(request.POST)
print (obj.is_valid()) # 这是方法,别忘记了加括号
print (obj.cleaned_data)
print (obj.errors)
return render(request, "index.html" ,{ 'obj' :obj})
|
index.html
1
2
3
4
5
6
7
|
<body>
<form action = "/index/" method = "POST" novalidate = "novalidate" >
{ % csrf_token % }
{{ obj.as_p }}
< input type = "submit" value = "提交" >
< / form>
< / body>
|
ModelForm常见参数
自定义字段名(html显示的字段)
如何定义http上定义的字段呢,自定义写成中文的?之前的用法是在Form里写上label。Model Form定义要用verbose_name
指定显示那些字段
1
2
3
4
|
class UserInfo(models.Model):
username = models.CharField(max_length = 32 , verbose_name = '用户' )
email = models.EmailField(verbose_name = '邮箱' )
user_type = models.ForeignKey(to = 'UserType' ,to_field = 'id' , verbose_name = '类型' )
|
如果不在model里定义,在modelForm里实现,利用labels
1
2
3
4
5
6
7
8
9
|
class UserInfoModelForm(forms.ModelForm):
class Meta:
model = models.UserInfo
fields = "__all__"
labels = {
'username' : '用户名' ,
'email' : '邮箱' ,
}
|
指定需要展示的字段
fields = "__all__"
上面展示所有的,也可以展示指定的列
1
2
|
fields = [ 'username' , 'email' ] # 显示指定列
exclude = [ 'username' ] # 排除指定列
|
错误信息
1
2
3
4
5
6
7
8
9
|
error_messages = {
'__all__' :{ # 整体错误信息
},
'email' : {
'required' : '邮箱不能为空' ,
'invalid' : '邮箱格式错误..' ,
}
}
|
给字段添加css属性
1
2
3
|
widgets = {
'username' : Fwidgets.Textarea(attrs = { 'class' : 'c1' })
}
|
ModelForm的验证
跟form一样,ModleForm里面也有is_valid
,cleaned_data
,errors
,
1
2
3
4
5
|
# Form验证:
UserInfoForm - > Form - > BaseForm( 包含is_valid等方法)
# ModelForm验证:
UserInfoModelForm - > ModelForm - > BaseModelForm - > BaseForm
|
ModelForm对数据库操作
添加数据
如果数据验证通过,直接调用save()方法,django会自动往数据库里添加一条数据(会根据modles里的字段一一对应)
1
2
|
if obj.is_valid():
obj.save() # 创建数据
|
如果在如下一对多、多对多关系中,如:
1
2
3
4
5
6
7
8
9
10
11
|
class UserType(models.Model):
caption = models.CharField(max_length = 32 )
class UserGroup(models.Model):
name = models.CharField(max_length = 32 )
class UserInfo(models.Model):
username = models.CharField(max_length = 32 )
email = models.EmailField()
user_type = models.ForeignKey(to = 'UserType' ,to_field = 'id' )
u2g = models.ManyToManyField(UserGroup)
|
这样的话,执行上面的obj.save()
会自动在UserInfo表和多对多关系表里都增加数据,灰常灰常方便。
1
2
3
4
5
6
7
8
9
10
11
12
|
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() # 等价以下三句
# instance = obj.save(False)
# instance.save()
# obj.save_m2m()
return render(request, 'index.html' ,{ 'obj' : obj})
|
修改数据
修改表数据是,记得把instance
信息也传进去,如:mf = UserInfoModelForm(request.POST,instance=user_obj)
不然是新建数据,而不是对某行数据进行修改。
编辑用户信息,新url方式保留默认数据
urls.py
1
2
|
url(r '^user_list/' , views.user_list),
url(r '^edit-(\d+)/' , views.user_edit),
|
views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
def user_list(request):
li = models.UserInfo.objects. all ().select_related( 'user_type' ) # 这里只能是外键,多对多字段也不可以
return render(request, 'user_list.html' ,{ 'li' : li})
def user_edit(request, nid):
# 获取当前id对象的用户信息
# 显示用户已经存在数据
if request.method = = "GET" :
user_obj = models.UserInfo.objects. filter ( id = nid).first()
mf = UserInfoModelForm(instance = user_obj) # 把默认数据传递进去
return render(request, 'user_edit.html' ,{ 'mf' : mf, 'nid' : nid})
elif request.method = = 'POST' :
# 数据修改的信息,给数据库的哪一行做修改?
user_obj = models.UserInfo.objects. filter ( id = nid).first()
mf = UserInfoModelForm(request.POST,instance = user_obj) # 指定给谁做修改
if mf.is_valid():
mf.save()
else :
print (mf.errors.as_json())
return render(request, 'user_edit.html' ,{ 'mf' : mf, 'nid' : nid})
|
user_list.html
1
2
3
4
5
6
7
|
<body>
<ul>
{ % for row in li % }
<li>{{ row.username }} - {{ row.user_type.caption }} - <a href = "/edit-{{ row.id }}/" >编辑< / a>< / li>
{ % endfor % }
< / ul>
< / body>
|
user_edit.html
1
2
3
4
5
6
7
|
<body>
<form method = "POST" action = "/edit-{{ nid }}/" >
{ % csrf_token % }
{{ mf.as_p }}
< input type = "submit" value = "提交" / >
< / form>
< / body>
|
转载于:https://www.cnblogs.com/weidaijie/p/10393789.html
django-Modelform相关推荐
- Django ModelForm操作及验证
一.内容回顾 Model- 数据库操作- 验证class A(MOdel): user = email = pwd = Form - class LoginForm(Form): email = fi ...
- Django ModelForm 组件的应用
ModelForm组件的应用 ModelForm 组件的创建: 1.创建一个类,该类继承 forms.ModelForm 2.大致组成部分 class ModelNameModelForm(form ...
- html表单中选择日期,Django:ModelForm中的日期选择器
在模型中,我有两个字段 from_date = models.DateField() to_date = models.DateField() widgets = { 'from_date' : Da ...
- python django web典型模块开发实战下载_Django实战 Python Web典型模块与项目开发
本书结合样例,介绍 Django 的基础知识.主要模块的开发以及权限管理等高级内容,并且通过图书管理系统.博客系统.车费管理系统 3 个项目的开发实战,使读者既能掌握 Django 的重要开发技术,又 ...
- Django REST framework API 指南(12):验证器
官方原文链接 本系列文章 github 地址 转载请注明出处 验证器 大多数情况下,您在 REST framework 中处理验证时,只需依赖默认的字段验证,或者在序列化类或字段类上编写明确的验证方法 ...
- django错误参考
1. Python manager出现以下错误 File "C:\Python27\lib\functools.py", line 56, in <lambda> '_ ...
- Django ModelForms
In this tutorial, we'll be discussing and implementing ModelForms in our Django Web Application. Do ...
- devops的五个要素_DevOps诗歌大满贯:DevOps艺术的五首诗
devops的五个要素 LISA已有 30年的历史,是世界上最重要的系统管理会议之一. 每年,它都会举办为期数百周的有关最新技术的深入教程和课程,其中包括数百名最优秀的sysadmin和基础设施专家. ...
- Flask框架 请求与响应 模板语法
目录 Flask框架 请求与响应 & 模板语法 简单了解Flask框架 Flask 框架 与 Django 框架对比 简单使用Flask提供服务 Flask 中的 Response(响应) F ...
- Django之ModelForm验证
一.简介 Django中Model负责操作数据库,并且具有简单的数据库验证功能(基本不用):Form用于用户请求的验证,具有强悍的数据库验证功能:ModelForm是将二者合二为一,即可用于数据库操作 ...
最新文章
- 3大主流NoSQL数据库性能对比测试报告
- 详解SDR/DDR/DDR2/SDRAM的功能及异同
- AndroidのUI设计研究(一)——自定义ProgressBar
- CentOS7使用nmcli实现网络日常管理及多网卡bond
- 洛谷.4172.[WC2006]水管局长(LCT Kruskal)
- 一个90后草根站长的内心独白
- duilib开发(十):动态添加控件
- 查看Windows的激活到期时间、具体版本号等具体系统信息
- 动作捕捉用于索并联机构中的理论验证
- 网站死链接检测工具 Xenu 汉化版
- 用jQuery做一个简单的用户注册页面
- 该应用程序从products.json加载数据
- Android WebView 因重定向无法正常goBack()的一种解决小方案
- 怎么下载优酷视频呢,你可以这样下
- wms仓库管理系统带来的效益
- Java 字符集编解码及乱码示例
- Spring Boot | 第零章:开启新纪元
- Thorui组件库的安装与使用
- 区块链网络安全(区块链网络安全论文)
- 全网最全安全加固指南
热门文章
- Docker监控方案(TIG)的研究与实践之Grafana
- 自行控制loadrunner的socket协议性能测试 (转)
- 一、nginx基本模块以及模块配置
- 基于Android平台的多分辨率解决方案[图]
- Node.js 体验-在Windows Azure工作者角色上托管Node.js
- C++实现 找出10000以内的完数
- windows 下使用composer
- Cllimbing Stairs [LeetCode 70]
- Linux如何关机与关机命令祥解
- PL/SQL 的一些用法