Django組件-ModelForm
阿新 • • 發佈:2019-02-02
tool ted syn ets 長度 tex oot return multi
模型表單ModelForm
一、基本用法
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
from django import forms
from django.utils.safestring import mark_safe from django.core.exceptions import ValidationError
from rbac import models
from django.utils.translation import ugettext_lazy
ICON_LIST = [
[ ‘fa-hand-scissors-o‘ , ‘<i aria-hidden="true" class="fa fa-hand-scissors-o"></i>‘ ],
[ ‘fa-hand-spock-o‘ , ‘<i aria-hidden="true" class="fa fa-hand-spock-o"></i>‘ ],
]
for item in ICON_LIST:
item[ 1 ] = mark_safe(item[ 1 ])
class BootStrapModelForm(forms.ModelForm):
def __init__( self , * args, * * kwargs):
super (BootStrapModelForm, self ).__init__( * args, * * kwargs)
# 統一給ModelForm生成字段添加樣式
for name, field in self .fields.items():
field.widget.attrs[ ‘class‘ ] = ‘form-control‘
"""
基本用法:
首先從django.forms導入ModelForm;
編寫一個自己的類,繼承ModelForm;
在新類裏,設置元類Meta;
在Meta中,設置model屬性為你要關聯的ORM模型,這裏是Menu;
在Meta中,設置fields屬性為你要在表單中使用的字段列表;列表裏的值,應該是ORM模型model中的字段名。
"""
class UserModelForm(BootStrapModelForm):
confirm_password = forms.CharField(label = ‘確認密碼‘ ) #
class Meta:
model = models.UserInfo
fields = [ ‘name‘ , ‘email‘ , ‘password‘ , ‘confirm_password‘ , ‘icon‘ ]
# fields = ‘__all__‘ #表示將映射的模型中的全部字段都添加到表單類中來
exclude = [ ‘pid‘ ] #表示將model中,除了exclude屬性中列出的字段之外的所有字段,添加到表單類中作為表單字段。
widgets = {
‘name‘ : forms.TextInput(attrs = { ‘class‘ : ‘form-control‘ }),
‘icon‘ : forms.RadioSelect(
choices = ICON_LIST,
attrs = { ‘class‘ : ‘clearfix‘ }
)
}
labels = {
‘name‘ : ugettext_lazy( ‘Writer‘ ),
}
help_texts = {
‘name‘ : ugettext_lazy( ‘Some useful help text.‘ ),
}
error_messages = {
‘name‘ : {
‘max_length‘ : ugettext_lazy( "This writer‘s name is too long." ),
},
}
def clean_confirm_password( self ):
"""
檢測密碼是否一致
:return:
"""
password = self .cleaned_data[ ‘password‘ ]
confirm_password = self .cleaned_data[ ‘confirm_password‘ ]
if password ! = confirm_password:
raise ValidationError( ‘兩次密碼輸入不一致‘ )
return confirm_password
# 可以在實例化一個表單時通過指定initial參數來提供表單中數據的初始值。
|
二、字段類型
生成的Form類中將具有和指定的模型字段對應的表單字段,順序為fields屬性列表中指定的順序。
每個模型字段有一個對應的默認表單字段。比如,模型中的CharField表現成表單中的CharField。模型中的ManyToManyField字段會表現成MultipleChoiceField字段。下面是完整的映射列表:
模型字段 | 表單字段 |
---|---|
AutoField | 在Form類中無法使用 |
BigAutoField | 在Form類中無法使用 |
BigIntegerField | IntegerField,最小-9223372036854775808,最大9223372036854775807. |
BooleanField | BooleanField |
CharField | CharField,同樣的最大長度限制。如果model設置了null=True,Form將使用empty_value |
CommaSeparatedIntegerField | CharField |
DateField | DateField |
DateTimeField | DateTimeField |
DecimalField | DecimalField |
EmailField | EmailField |
FileField | FileField |
FilePathField | FilePathField |
FloatField | FloatField |
ForeignKey | ModelChoiceField |
ImageField | ImageField |
IntegerField | IntegerField |
IPAddressField | IPAddressField |
GenericIPAddressField | GenericIPAddressField |
ManyToManyField | ModelMultipleChoiceField |
NullBooleanField | NullBooleanField |
PositiveIntegerField | IntegerField |
PositiveSmallIntegerField | IntegerField |
SlugField | SlugField |
SmallIntegerField | IntegerField |
TextField | CharField,並帶有widget=forms.Textarea參數 |
TimeField | TimeField |
URLField | URLField |
-
ForeignKey被映射成為表單類的django.forms.ModelChoiceField,它的選項是一個模型的QuerySet,也就是可以選擇的對象的列表,但是只能選擇一個。
-
ManyToManyField被映射成為表單類的django.forms.ModelMultipleChoiceField,它的選項也是一個模型的QuerySet,也就是可以選擇的對象的列表,但是可以同時選擇多個,多對多嘛。
- 如果模型字段設置blank=True,那麽表單字段的required設置為False。 否則,required=True。
- 表單字段的label屬性根據模型字段的verbose_name屬性設置,並將第一個字母大寫。
- 如果模型的某個字段設置了editable=False屬性,那麽它表單類中將不會出現該字段。道理很簡單,都不能編輯了,還放在表單裏提交什麽?
- 表單字段的
help_text
設置為模型字段的help_text
。 - 如果模型字段設置了choices參數,那麽表單字段的widget屬性將設置成Select框,其選項來自模型字段的choices。選單中通常會包含一個空選項,並且作為默認選擇。如果該字段是必選的,它會強制用戶選擇一個選項。 如果模型字段具有default參數,則不會添加空選項到選單中。
三、完整示例
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#models.py
from django.db import models
TITLE_CHOICES = (
( ‘MR‘ , ‘Mr.‘ ),
( ‘MRS‘ , ‘Mrs.‘ ),
( ‘MS‘ , ‘Ms.‘ ),
)
class Author(models.Model):
name = models.CharField(max_length = 100 )
title = models.CharField(max_length = 3 , choices = TITLE_CHOICES)
birth_date = models.DateField(blank = True , null = True )
def __str__( self ): # __unicode__ on Python 2
return self .name
class Book(models.Model):
name = models.CharField(max_length = 100 )
authors = models.ManyToManyField(Author)
#myforms.py
from django import forms
class AuthorForm(forms.ModelForm):
class Meta:
model = models.Author
fields = [ ‘name‘ , ‘title‘ , ‘birth_date‘ ]
class BookForm(forms.ModelForm):
class Meta:
model = models.Book
fields = [ ‘name‘ , ‘authors‘ ]
#上面的ModelForm子類基本等同於下面的定義方式(唯一的區別是save()方法):
from django import forms
class AuthorForm(forms.Form):
name = forms.CharField(max_length = 100 )
title = forms.CharField(
max_length = 3 ,
widget = forms.Select(choices = TITLE_CHOICES),
)
birth_date = forms.DateField(required = False )
class BookForm(forms.Form):
name = forms.CharField(max_length = 100 )
authors = forms.ModelMultipleChoiceField(queryset = Author.objects. all ())
|
四、ModelForm的驗證
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
def menu_add(request):
if request.method = = ‘POST‘ :
form = MenuModelForm(data = request.POST)
if form.is_valid():
form.save()
return redirect(memory_reverse(request, ‘rbac:menu_list‘ ))
form = MenuModelForm()
return render(request, ‘rbac/change.html‘ , { ‘form‘ : form})
def menu_edit(request, pk):
obj = models.Menu.objects. filter ( id = pk).first()
if not obj:
return HttpResponse( ‘菜單不存在‘ )
if request.method = = ‘POST‘ :
form = MenuModelForm(instance = obj, data = request.POST)
if form.is_valid():
form.save()
return redirect(memory_reverse(request, ‘rbac:menu_list‘ ))
form = MenuModelForm(instance = obj)
return render(request, ‘rbac/change.html‘ , { ‘form‘ : form})
|
Django組件-ModelForm