Day23內容回顧--缺失,遺憾成狗。html
一:Model(2個功能)前端
-數據庫操做;python
-驗證,只有一個clean方法能夠做爲鉤子。正則表達式
二:Form(專門來作驗證的)--------根據form裏面寫的類,類裏面有字段,這個字段是內置的正則表達式。數據庫
例如:-class LoginForm(Form): email=fields.EmailField()django
-is_valid(觸發驗證功能) ->每個字段進行正則(用的是字段內置的正則)+clean_字段 -> clean(__all__) -> _post_clean。json
form的鉤子,先進行每個字段正則表達式驗證,而後每個字段的方法,而後進行clean,clean完了之後是post cleanapp
email的錯誤信息放在email [大列表裏面了], 總體的錯誤信息放在了 __all__ 裏面了。函數
-cleaned_datapost
-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()