一. 建立一個ModelForm
1.1 使用之前需要導入對應app中的models和Django送出的ModelForm類
from django.forms import ModelForm
from app01.models import Host
from django.forms import widgets #插件,接下來會用到
from django.core.exceptions import ValidationError
1.2 建立一個類,并繼承ModelForm
class HostModelForm(ModelForm): #建立1個類,繼承ModelForm
class Meta: #在内部定義一個Meta類,注意這個類名是固定不變的
model = Host #對應models.py中哪個類(哪個表)
fields = '__all__' #表示使用models.Host類中所有字段
# fields = ('hostname','ip','port','dep') #也可以這樣選擇指定字段
ModelForm常用的class Meta配置
class Meta:
model = models.UserInfo #結尾不用加逗号
fields = '__all__'
# fields = ['username','email']
# exclude = ['username'] # 除了 XX字段,其他都使用
labels = { # label 名稱
'username': '使用者名',
'email': '郵箱',
}
help_texts = { # 幫助資訊
'username': '...'
}
widgets = {
'username': Fwidgets.Textarea(attrs={'class': 'c1'})
}
error_messages = { # 自定義錯誤
'__all__':{
},
'email': {
'required': '郵箱不能為空',
'invalid': '郵箱格式錯誤..',
}
}
field_classes = { #字段類型,可以強制修改成其他類型
# 'email': Ffields.URLField
}
# localized_fields=('ctime',)
二. ModelForm生成Html和資料驗證
2.1 生成空表單
forms = HostModelForm() # 生成空的表單
2.2 在表單中顯示初始資料
hostobj =models.Host.objects.get(id=1)
forms = HostModelForm(instance = hostobj) # instance 對應模型執行個體
2.3 驗證表單資料并儲存
forms = HostModelForm(request.POST)
if forms.is_valid(): # 驗證成功則儲存modelsform
forms.save() # 這一步會直接将資料儲存至資料庫
注意:此時,forms.save()不僅儲存目前對象執行個體,還儲存執行個體對應跨表關系(外鍵、多對多等)
三. 前端頁面展示form表
在模版中展示指定字段
<form method="post" novalidate>
{% csrf_token %}
<p>{{ forms.hostname.label }}: {{ forms.hostname }}{{ forms.hostname.errors.0 }}</p>
<p>{{ forms.ip.label }}: {{ forms.ip }}{{ forms.ip.errors.0 }}</p>
<p>{{ forms.port.label }}: {{ forms.port }}{{ forms.port.errors.0 }}</p>
<input type="submit" value="送出">
</form>
如果嫌上面這種方法麻煩,還可以在模版中循環forms執行個體,以列出每個字段
<form method="post" novalidate>
{% csrf_token %}
{% for form in forms %}
<p>{{ form.label }}: {{ form }}{{ form.errors.0 }}</p>
{% endfor %}
<input type="submit" value="送出">
</form>
四. 示例
4.1 在app中建立一個forms.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author : Cai Guangyin
from django.forms import ModelForm
from app01.models import Host
from django.forms import widgets
from django.core.exceptions import ValidationError
class HostModelForm(ModelForm): #建立1個類,繼承ModelForm
class Meta:
model = Host #對應models.py中哪個類(哪個表)
fields = '__all__' #表示使用models.Host類中所有字段
# fields = ('hostname','ip','port','dep') #也可以這樣選擇指定字段
error_messages = { #自定義錯誤提示資訊
'hostname':{
'required':'使用者名不能為空'
},
'ip':{
'required':'IP不能為空',
'invalid':'IP位址格式錯誤'
},
'port':{
'required':'端口不能為空'
},
'dep': {
'required': '部門不能為空'
},
'userinfo': {
'required': '所屬使用者不能為空'
},
}
labels = { #自定義label标簽顯示的内容
'hostname':'主機名',
'ip':'IP',
'port':'端口',
'dep':'部門',
'userinfo':'所屬使用者'
}
widgets = { # 自定義插件,注意必須加s,因為是複數,寫widget不起作用
'hostname': widgets.TextInput(attrs={'class':'form-control'}),
'ip': widgets.TextInput(attrs={'class':'form-control'}),
'port': widgets.TextInput(attrs={'class':'form-control'}),
'dep': widgets.Select(attrs={'class':'form-control'}),
'userinfo': widgets.SelectMultiple(attrs={'class':'form-control'}),
}
def clean_port(self): #也可以自定義鈎子函數對字段進行驗證
value = self.cleaned_data['port']
if int(value) > 65535:
raise ValidationError('端口号不能大于65535')
return value
4.2 views.py
from django.shortcuts import render
from .models import *
from .forms import HostModelForm
# Create your views here.
def index(request):
forms = HostModelForm() #建立空表單
if request.method == 'POST':
forms = HostModelForm(request.POST) #送出資料
if forms.is_valid(): #驗證資料
forms.save()
return render(request,'index.html',locals())
def edit_host(request):
host_obj = Host.objects.filter(pk=1).first()
forms = HostModelForm(instance=host_obj) #編輯時顯示預設資料
if request.method == 'POST':
# host_obj = Host.objects.filter(pk=1).first()
# forms = HostModelForm(request.POST) #向modelform中傳遞資料
forms = HostModelForm(data=request.POST,instance=host_obj) #編輯儲存時,需要将data和instance都傳入
if forms.is_valid():
forms.save()
return render(request,'edithost.html',locals())
注意:在修改表單(表單中有初始值),送出驗證時,需要傳入data和instance兩個參數,如: forms = HostModelForm(data=request.POST,instance=host_obj)
4.3 模版檔案
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post" novalidate>
{% csrf_token %}
{% for form in forms %}
<p>{{ form.label }}: {{ form }}{{ form.errors.0 }}</p>
{% endfor %}
<input type="submit" value="送出">
</form>
</body>
</html>