1. 程式人生 > >Django組件-ModelForm

Django組件-ModelForm

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