Day24-ModelForm操作及验证
Day23内容回顾--缺失,遗憾成狗。
一:Model(2个功能)
-数据库操作;
-验证,只有一个clean方法可以作为钩子。
二:Form(专门来做验证的)--------根据form里面写的类,类里面有字段,这个字段是内置的正则表达式。
例如:-class LoginForm(Form): email=fields.EmailField()
-is_valid(触发验证功能) ->每一个字段进行正则(用的是字段内置的正则)+clean_字段 -> clean(__all__) -> _post_clean。
form的钩子,先进行每一个字段正则表达式验证,然后每一个字段的方法,然后进行clean,clean完了以后是post clean
email的错误信息放在email [大列表里面了], 整体的错误信息放在了 __all__ 里面了。
-cleaned_data
-error
建议分开使用上面的两个模块:Model+Form,这样可以降低耦合。但是代码有重复。
Day24: 环境搭建,参考http://www.cnblogs.com/momo8238/p/7508677.html
一,基于form来做。
创建2张表备用,2张表之间用ForeignKey进行关联:
models.py
from django.db import models # Create your models here.
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')
创建
python manage.py makemigrations
python manage.py migrate
2. 如果我想在index.html页面上对UserInfo表进行操作,那么应该把UserInfo 表中的所有信息从后台传送过来。把所有的字段重新创建一遍。
用Form方法的话,需要自己写field字段。 用ModelForm的话,字段是自己从类里面提取过来的。
views.py
# Create your views here. 用Form方式实现
from django.shortcuts import render
from django import forms
from django.forms import fields
from app01 import models class UserInfoForm(forms.Form):
username = fields.CharField(max_length=32)
email=fields.EmailField()
user_type=fields.ChoiceField(
choices=models.UserType.objects.values_list('id','caption')
#forms下面是用field字段来进行验证的。forms下面没有foreignKey字段,只有choicefield,然后通过choices把另外一张表里面的内容都关联过来。在页面上把用户类型作为一个列表展示出来
) def index(request):
obj=UserInfoForm()
return render(request,'index.html',{'obj':obj})
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% csrf_token %}
{{obj.as_p}}
</body>
</html>
运行效果:
3. 让user_type每一次都做更新操作,需要重构函数
说明见下图:
具体说明可以参考day23
def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices=models.UserType.objects.values_list('id','caption')
4. 完善index.html函数,用form表单提交
{% csrf_token %} 密文显示
{{csrf_token }} 在前端页面生成字符串
<!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>
页面效果:
5. 一点提交,数据就传到了后台。
obj.is_valid() #是否通过验证
obj.cleaned_data() #所有的正确信息
obj.errors() #所有的错误信息
models.UserInfo.objects.create(**obj.cleaned_data) #如果数据正确,则创建。是字典格式。
models.UserInfo.objects.filter(id=1).update(**obj.cleaned_data) #找到主键后自动更新 程序粘贴: views.py
# Create your views here. 用Form方式实现
from django.shortcuts import render
from django import forms
from django.forms import fields
from app01 import models class UserInfoForm(forms.Form):
username = fields.CharField(max_length=32)
email=fields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id') fields中没有foreignkey
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') def index(request):
if request.method=='GET':
obj=UserInfoForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoForm(request.POST)
obj.is_valid()
obj.cleaned_data()
obj.errors()
#models.UserInfo.objects.create(**obj.cleaned_data)
#models.UserInfo.objects.filter(id=1).update(**obj.cleaned_data)
return render(request, 'index.html', {'obj': obj})
index.html
<!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>
models.py
from django.db import models # Create your models here.
class UserType(models.Model):
caption=models.CharField(max_length=32) class UserInfo(models.Model):
username = models.CharField(verbose_name='用户名',max_length=32)
email=models.EmailField()
user_type=models.ForeignKey(to='UserType',to_field='id')
urls.py
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),
]
二,基于ModelForm来做。
1. class UserInfoModelForm(forms.ModelForm): 它也能帮我们自动生成HTML标签。 views.py
# 基于ModelForm方式来实现
from django.shortcuts import render
from app01 import models from django import forms
from django.forms import fields class UserInfoModelForm(forms.ModelForm):
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把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)
return render(request, 'index.html', {'obj': obj})
效果:
2.用Form时,字段是自己定义的。所以如果想显示中文的话,用label标签就可以了。 views.py
# 基于Form方式来实现
from django.shortcuts import render
from django import forms
from django.forms import fields
from app01 import models class UserInfoForm(forms.Form):
username = fields.CharField(max_length=32,label='用户名')
email=fields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id') fields中没有foreignkey
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') def index(request):
if request.method=='GET':
obj=UserInfoForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoForm(request.POST)
obj.is_valid()
obj.cleaned_data()
obj.errors()
#models.UserInfo.objects.create(**obj.cleaned_data)
#models.UserInfo.objects.filter(id=1).update(**obj.cleaned_data)
return render(request, 'index.html', {'obj': obj})
效果如下:
用ModelForm时,前端页面中的字段是从相关联的类里面直接提取过来的,两者之间有耦合。自己不用再写了。 如果想要显示中文字段名的话,需要verbose_name='用户'
效果:
3.
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
exclude=['username'] #把username列排除在外了。
效果展示1:
效果展示2:
4. 往UserType里面写一条数据备用:
用form方法的时候,验证功能的函数其实是写在BaseForm里的:UserInfoForm-->继承了Form--->继承了BaseForm(is_valid......)
点击提交的时候,modelform也可以做验证。UserInfoModelForm-->继承了ModelForm--->继承了BaseModelForm--->继承了BaseForm(is_valid......)
UserInfoModelForm下面也应该有obj.is_valid(), obj.cleaned_data, obj.errors 等方法。
ModelForm 做验证的时候与Form方法是一样的。
效果1:
效果2:
三,程序粘贴:
1. 基于form方法的views.py
# 基于Form方式来实现
from django.shortcuts import render
from django import forms
from django.forms import fields
from app01 import models class UserInfoForm(forms.Form):
username = fields.CharField(max_length=32,label='用户名')
email=fields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id') fields中没有foreignkey
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') def index(request):
if request.method=='GET':
obj=UserInfoForm()
return render(request,'index.html',{'obj':obj})
elif request.method=='POST':
obj=UserInfoForm(request.POST)
obj.is_valid()
obj.cleaned_data()
obj.errors()
#models.UserInfo.objects.create(**obj.cleaned_data)
#models.UserInfo.objects.filter(id=1).update(**obj.cleaned_data)
return render(request, 'index.html', {'obj': obj})
2. 基于modelform方法的views.py
# 基于ModelForm方式来实现
from django.shortcuts import render,HttpResponse
from app01 import models from django import forms
from django.forms import fields def orm(request):
#models.UserType.objects.create(caption='Alex')
return HttpResponse('orm') class UserInfoModelForm(forms.ModelForm):
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。 class UserInfoForm(forms.Form):
username = fields.CharField(max_length=32)
email=fields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id')
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') 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})
3.index.html
<!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>
4.models.py
from django.db import models # Create your models here.
class UserType(models.Model):
caption=models.CharField(max_length=32) class UserInfo(models.Model):
username = models.CharField(verbose_name='用户',max_length=32)
email=models.EmailField()
user_type=models.ForeignKey(to='UserType',to_field='id')
5.urls.py
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'^orm/', views.orm),
]
4.1 labels=None, # 提示信息
如果不想在Models原表中写verbose_name的话,可以在定义类的时候在ModelForm中写提示信息。
原来的效果:
现在也可以在modelform中写提示信息:labels是个字典格式,可以写多个。
4.2 help_texts=None, # 帮助提示信息
4.3 widgets=None, # 自定义插件以及样式。
4.4 错误信息 error_messages=None, # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)
前端:
后台收集的错误信息:
错误信息的显示:
整体的错误信息也可以在这里用同样的方法定义,用的是__all__:{ }。 每一项的错误信息应该放到一个字典中。
4.5 field_classes=None # 自定义字段类 (也可以自定义字段)
我想把邮箱格式的正则表达式改为url的格式进行验证。
# 基于ModelForm方式来实现
from django.shortcuts import render,HttpResponse
from app01 import models
from django import forms
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
def orm(request):
#models.UserType.objects.create(caption='Alex')
return HttpResponse('orm') class UserInfoModelForm(forms.ModelForm):
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。
#labels={'username':'请填入用户名'}
#help_texts={'username':'请把你的名字写对'}
#widgets={'username':Fwidgets.Textarea(attrs={'class':'c1'})}
error_messages={
'__all__':{},
'email':{
'required':'邮箱不能为空',
'invalid':'邮箱格式错误',
}
}
field_classes={
'email':Ffields.URLField #这里只能填类,不能加括号,加上括号就变成对象了。
}
class UserInfoForm(forms.Form):
username = Ffields.CharField(max_length=32)
email=Ffields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id')
user_type=Ffields.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') 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.as_json())
return render(request, 'index.html', {'obj': obj})
效果:
4.6 把时间本地化的时候,需要在setting里面进行一下当前时区的设置。
localized_fields
=
(
'birth_date'
,)
# 本地化,如:根据不同时区显示数据
如:
数据库中
2016
-
12
-
27
04
:
10
:
57
setting中的配置
TIME_ZONE
=
'Asia/Shanghai'
USE_TZ
=
True
则显示:
2016
-
12
-
27
12
:
10
:
57
4.7 切记 class Meta里面最容易犯的错误就是加逗号。千万不要加逗号
ModelForm的所有字段 a. class Meta: model, # 对应Model的哪个类,哪张表。 fields=None, # 字段 exclude=None, # 排除字段 labels=None, # 提示信息 help_texts=None, # 帮助提示信息 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={...})
五 第一个省事的地方是不用写字段了。第二个省事的地方是验证通过以后,用save方式就可以直接添加到数据库中了。
程序:
效果:
六,再新建一张表,做多对多的示例。
6.1 models.py
from django.db import models 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(verbose_name='用户',max_length=32)
username = models.CharField(max_length=32)
email=models.EmailField()
user_type=models.ForeignKey(to='UserType',to_field='id')
u2g=models.ManyToManyField(UserGroup)
在usergroup表中新建几条数据
def orm(request):
models.UserGroup.objects.create(name='CEO')
models.UserGroup.objects.create(name='CFO')
models.UserGroup.objects.create(name='COO')
return HttpResponse('orm')
如下:
页面效果:发现多对多也显示出来了。
6.2 页面上新建然后保存数据
点击提交,就保存到数据库表中了。
多对多表中数据也增加了。
这个save的功能太强大了。
6.3 views.py
# 基于ModelForm方式来实现
from django.shortcuts import render,HttpResponse
from app01 import models
from django import forms
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
def orm(request):
#models.UserGroup.objects.create(name='CEO')
#models.UserGroup.objects.create(name='CFO')
#models.UserGroup.objects.create(name='COO')
return HttpResponse('orm') class UserInfoModelForm(forms.ModelForm):
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。
#labels={'username':'请填入用户名'}
#help_texts={'username':'请把你的名字写对'}
#widgets={'username':Fwidgets.Textarea(attrs={'class':'c1'})}
error_messages={
'__all__':{},
'email':{
'required':'邮箱不能为空',
'invalid':'邮箱格式错误',
}
}
#field_classes={'email':Ffields.URLField}
class UserInfoForm(forms.Form):
username = Ffields.CharField(max_length=32)
email=Ffields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id')
user_type=Ffields.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') 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()
#print(obj.is_valid())
#print(obj.cleaned_data)
#print(obj.errors.as_json())
return render(request, 'index.html', {'obj': obj})
七,obj.save()的拆分
查看源码可知,save包含两部分:
instance.save(当前这个model对象,意思就是可以把当前表save一下)
obj.save_m2m( ) save ManyToMany,其实就是把两步save拆开了。
7.1 测试 instance.save
测试效果:
7.2 小结:ModelForm可以帮我们生成HTML标签,也可以帮忙做验证,验证完了以后还可以直接保存在数据库中。
八,基于modelform实现添加数据的功能
models.UserInfo.objects.all().select_related('user_type','u2g') #跨表
8.1 添加user_list函数
# 基于ModelForm方式来实现
from django.shortcuts import render,HttpResponse
from app01 import models
from django import forms
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
def orm(request):
#models.UserGroup.objects.create(name='CEO')
#models.UserGroup.objects.create(name='CFO')
#models.UserGroup.objects.create(name='COO')
return HttpResponse('orm') class UserInfoModelForm(forms.ModelForm):
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。
#labels={'username':'请填入用户名'}
#help_texts={'username':'请把你的名字写对'}
#widgets={'username':Fwidgets.Textarea(attrs={'class':'c1'})}
error_messages={
'__all__':{},
'email':{
'required':'邮箱不能为空',
'invalid':'邮箱格式错误',
}
}
#field_classes={'email':Ffields.URLField}
class UserInfoForm(forms.Form):
username = Ffields.CharField(max_length=32)
email=Ffields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id')
user_type=Ffields.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') 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()#这个save实现的时候,其实内部包含了2个步骤。可以拆开。
instance=obj.save(False) #什么也没干
instance.save() #只会保存当前这个类,而不会保存manytomany
obj.save_m2m() #保存manytomany
#print(obj.is_valid())
#print(obj.cleaned_data)
#print(obj.errors.as_json())
return render(request, 'index.html', {'obj': obj}) def user_list(request):
li=models.UserInfo.objects.all().select_related('user_type') #先把userinfo中的数据取出来
return render(request,'user_list.html',{'li':li})
user_list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
{% for row in li %}
<li>{{row.username}}-{{row.user_type.caption}}</li>
{% endfor %}
</ul>
</body>
</html>
页面效果:
8.2 最终想要达到的效果:
程序粘贴:
models.py
from django.db import models 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(verbose_name='用户',max_length=32)
username = models.CharField(max_length=32)
email=models.EmailField()
user_type=models.ForeignKey(to='UserType',to_field='id')
u2g=models.ManyToManyField(UserGroup)
views.py
# 基于ModelForm方式来实现
from django.shortcuts import render,HttpResponse
from app01 import models
from django import forms
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
def orm(request):
#models.UserGroup.objects.create(name='CEO')
#models.UserGroup.objects.create(name='CFO')
#models.UserGroup.objects.create(name='COO')
return HttpResponse('orm') class UserInfoModelForm(forms.ModelForm):
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。
#labels={'username':'请填入用户名'}
#help_texts={'username':'请把你的名字写对'}
#widgets={'username':Fwidgets.Textarea(attrs={'class':'c1'})}
error_messages={
'__all__':{},
'email':{
'required':'邮箱不能为空',
'invalid':'邮箱格式错误',
}
}
#field_classes={'email':Ffields.URLField}
class UserInfoForm(forms.Form):
username = Ffields.CharField(max_length=32)
email=Ffields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id')
user_type=Ffields.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') 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()#这个save实现的时候,其实内部包含了2个步骤。可以拆开。
instance=obj.save(False) #什么也没干
instance.save() #只会保存当前这个类,而不会保存manytomany
obj.save_m2m() #保存manytomany
#print(obj.is_valid())
#print(obj.cleaned_data)
#print(obj.errors.as_json())
return render(request, 'index.html', {'obj': obj}) def user_list(request):
li=models.UserInfo.objects.all().select_related('user_type') #先把userinfo中的数据取出来
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) #instance传进来表示更新,不加的话表示新建了一条数据。
if mf.is_valid():
mf.save()
else:
print(mf.errors.as_json())
return render(request, 'user_edit.html', {'mf': mf, 'nid': nid})
user_edit.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="POST" action="/edit-{{nid}}/">
{% csrf_token %}
{{mf.as_p}}
<input type="submit" value="提交"/>
</form> </body>
</html>
user_list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
{% for row in li %}
<li>{{row.username}}-{{row.user_type.caption}}-<a href="/edit-{{row.id}}/">编辑</a></li>
{% endfor %}
</ul>
</body>
</html>
index.html
<!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>
urls.py
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'^user_list/', views.user_list),
url(r'^edit-(\d+)/', views.user_edit),
url(r'^orm/', views.orm),
]
8.3 补充
ModelForm:通过配置生成标签,用is_valid 进行验证,通过save进行保存。
ModelForm也可以自己定义钩子,与Form的用法一样。
在UserInfoModelForm中也可以定义新的字段。比如 username+password 可以从数据库中获取,但是像一个月内免登陆就不需要提交到数据库。像这个字段我们就可以在UserInfoModelForm中单独定义。
views.py
# 基于ModelForm方式来实现
from django.shortcuts import render,HttpResponse
from app01 import models
from django import forms
from django.forms import fields as Ffields
from django.forms import widgets as Fwidgets
def orm(request):
#models.UserGroup.objects.create(name='CEO')
#models.UserGroup.objects.create(name='CFO')
#models.UserGroup.objects.create(name='COO')
return HttpResponse('orm') class UserInfoModelForm(forms.ModelForm):
#自定义额外的字段,比如是否要保存一个月内免登陆。
is_remember=Ffields.CharField(
widget=Fwidgets.CheckboxInput()
)
class Meta:
model=models.UserInfo #指去哪个类里面去获取字段,以后也可以做增删改查。
fields='__all__' #代指的是所有的field字段
#fields=['username'] #还可以是一个列表,可以选择要展示哪几列,只展示username这一列
#exclude=['username'] #把username列排除在外了。
#labels={'username':'请填入用户名'}
#help_texts={'username':'请把你的名字写对'}
#widgets={'username':Fwidgets.Textarea(attrs={'class':'c1'})}
error_messages={
'__all__':{},
'email':{
'required':'邮箱不能为空',
'invalid':'邮箱格式错误',
}
}
#field_classes={'email':Ffields.URLField}
def clean_username(self):
old=self.cleaned_data['username']
return old class UserInfoForm(forms.Form):
username = Ffields.CharField(max_length=32)
email=Ffields.EmailField()
#user_type=fields.ForeignKey(to='UserType',to_field='id')
user_type=Ffields.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') 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()#这个save实现的时候,其实内部包含了2个步骤。可以拆开。
instance=obj.save(False) #什么也没干
instance.save() #只会保存当前这个类,而不会保存manytomany
obj.save_m2m() #保存manytomany
#print(obj.is_valid())
#print(obj.cleaned_data)
#print(obj.errors.as_json())
return render(request, 'index.html', {'obj': obj}) def user_list(request):
li=models.UserInfo.objects.all().select_related('user_type') #先把userinfo中的数据取出来
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) #instance传进来表示更新,不加的话表示新建了一条数据。
if mf.is_valid():
mf.save()
else:
print(mf.errors.as_json())
return render(request, 'user_edit.html', {'mf': mf, 'nid': nid})
效果:
九,总结
一,ModelForm => 可以做验证,可以做数据库操作。
Model+Form => 验证+数据库操作
-class LoginModelForm(XXXX):
利用model.A中的字段
1.生成html标签: class Meta:...
2.mf=xxxModelForm(instance=ModelObj)
3.额外的标签,
4.各种验证 is_valid()->各种钩子...
跟form的钩子一模一样,先进行每一个字段正则表达式验证,然后每一个字段的方法,然后进行clean,clean完了以后是post clean
5.mf.save()
############或者下面的###############
instance=mf.save(False)
instance.save()
mf.save_m2m()
Day24-ModelForm操作及验证的更多相关文章
- django(7)modelform操作及验证、ajax操作普通表单数据提交、文件上传、富文本框基本使用
一.modelForm操作及验证 1.获取数据库数据,界面展示数据并且获取前端提交的数据,并动态显示select框中的数据 views.py from django.shortcuts import ...
- Django ModelForm操作及验证
一.内容回顾 Model - 数据库操作 - 验证 class A(MOdel): user = email = pwd = Form - class LoginForm(Form): email = ...
- Django(九)上:ModelForm操作
一.内容回顾 Model - 数据库操作 - 验证 class A(MOdel): user = email = pwd = Form - class LoginForm(Form): email = ...
- Python开发【Django】:ModelForm操作
ModelForm 内容回顾: Model - 数据库操作 - 验证 class A(MOdel): user = email = pwd = Form class LoginForm(Form): ...
- Django使用普通表单、Form、以及modelForm操作数据库方式总结
Django使用普通表单.Form.以及modelForm操作数据库主要应用于增删该查的情景下,流程通用如下,只是实现方式不一样: 进入填写表单页面: 在表单页面填写信息,并提交: 表单数据验证 验证 ...
- web框架-(七)Django补充---models进阶操作及modelform操作
通过之前的课程我们可以对于Django的models进行简单的操作,今天了解下进阶操作和modelform: 1. Models进阶操作 1.1 字段操作 AutoField(Field) - int ...
- Django ModelForm表单验证
ModelForm 在使用Model和Form时,都需要对字段进行定义并指定类型,通过ModelForm则可以省去From中字段的定义 应用场景:定制model admin 的时候可以使用.适用于小业 ...
- modelform的操作以及验证
1,model的两个功能 1,数据库操作 2,验证只有一个clean方法作为钩子来操作,方法比较少 2,form(专门用来做验证的) 根据form里面写的类,类里面的字段,这些字段里有内置的的正则表达 ...
- ModelForm操作
ModelForm a. class Meta: model, # 对应Model的 fields=None, # 字段 exclude=None, # 排除字段 labels=None, # 提示信 ...
随机推荐
- Nginx 通过 Lua + Redis 实现动态封禁 IP
一.背景 为了封禁某些爬虫或者恶意用户对服务器的请求,我们需要建立一个动态的 IP 黑名单.对于黑名单之内的 IP ,拒绝提供服务. 二.架构 实现 IP 黑名单的功能有很多途径: 1.在操作系统层面 ...
- Python-类与对象
类与对象的概念 类即类别.种类,是面向对象设计最重要的概念,从一小节我们得知对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体. 那么问题来了,先有的一个个具体存在的对象(比如一个具 ...
- Winform MDI窗体切换不闪烁的解决办法(测试通过)
https://stackoverflow.com/questions/5817632/beginupdate-endupdate-for-datagridview-request SuspendLa ...
- Python之json使用
一.概念 json是一种通用的数据类型,任何语言都认识 接口返回的数据类型都是json 长得像字典,形式也是k-v { } 其实json是字符串 字符串不能用key.value来取值,要先转成字典才可 ...
- 从零开始搭建VUE项目
前言: 此样板面向大型,严肃的项目,并假定您对Webpack和vue-loader有些熟悉. 请务必阅读vue-loader的常见工作流配方的文档. 如果您只想尝试vue-loader或者鞭打一个快速 ...
- 关于spring的源码的理解
从最基础的Hello World开始. spring的Hello World就三行代码: public void test() { ApplicationContext context = new C ...
- jQuery EasyUI布局容器layout实例精讲
这个布局容器,有五个区域:北.南.东.西和中心. 他中心地区面板是必需的,但是边缘地区面板是可选的.每一个边缘地区面板可以缩放的拖动其边境, 他们也可以通过点击其收缩触发.布局可以嵌套,从而用户可以建 ...
- 动态SQL3
Oracle的批量操作 Oracle不支持VALUES(),(),()这种方式,所以不能用上一节所讲的方法. 有时候业务会包含很多次数据库操作,为了减少数据库连接,我们会选择一次提交大量sql, 这时 ...
- java学习之—栈
/** * 栈 * Create by Administrator * 2018/6/11 0011 * 上午 10:20 **/ public class StackX { private int ...
- drf图片字段序列化完整路径
一.需求 前端需要它想要的数据格式: 原有的数据格式: 二.定制化: 1.可以嵌套序列化pol_type,lit_des,area_detail,但结构如下: class ChrDetailSeria ...