Django組件-ModelForm

模型表單ModelForm

1、基本用法

class BookForm(forms.ModelForm):

    class Meta:
        model = models.Book
        fields = "__all__"
        labels = {
            "title": "書名",
            "price": "價格"
        }
        widgets = {
            "password": forms.widgets.PasswordInput(attrs={"class": "c1"}),
        }

2、class Meta下經常使用參數

model = models.Book  # 對應的Model中的類
fields = "__all__"  # 字段,若是是__all__,就是表示列出全部的字段
exclude = None  # 排除的字段
labels = None  # 提示信息
help_texts = None  # 幫助提示信息
widgets = None  # 自定義插件
error_messages = None  # 自定義錯誤信息

3、ModelForm的驗證和save()方法

  • 與普通的Form表單驗證類型相似,ModelForm表單的驗證在調用is_valid() 或訪問errors 屬性時隱式調用。
  • 能夠像使用Form類同樣自定義局部鉤子方法和全局鉤子方法來實現自定義的校驗規則。
  • 若是不重寫具體字段並設置validators屬性的化,ModelForm是按照模型中字段的validators來校驗的。
  • 每一個ModelForm還具備一個save()方法。 這個方法根據表單綁定的數據建立並保存數據庫對象。
  • ModelForm的子類能夠接受現有的模型實例做爲關鍵字參數instance;若是提供此功能,則save()將更新該實例。
  • 若是沒有提供,save() 將建立模型的一個新實例:
from myapp.models import Book
from myapp.forms import BookForm

# 根據POST數據建立一個新的form對象
form_obj = BookForm(request.POST)

# 建立書籍對象
new_ book = form_obj.save()

# 基於一個書籍對象建立form對象
edit_obj = Book.objects.get(id=1)

# 使用POST提交的數據更新書籍對象
form_obj = BookForm(request.POST, instance=edit_obj)
form_obj.save()
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參數來提供表單中數據的初始值。
實例
def menu_add(request):
    if request.method == 'GET':
        form = MenuModelForm()
        return render(request, 'rbac/change.html', {'form': form})
 
    form = MenuModelForm(data=request.POST)
    if form.is_valid():
        form.save()
        return redirect(memory_reverse(request, 'rbac:menu_list'))
 
    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 == 'GET':
        form = MenuModelForm(instance=obj)
        return render(request, 'rbac/change.html', {'form': form})
 
    form = MenuModelForm(instance=obj, data=request.POST)
    if form.is_valid():
        form.save()
        return redirect(memory_reverse(request, 'rbac:menu_list'))
 
    return render(request, 'rbac/change.html', {'form': form})
ModelForm的驗證
#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())
Form和ModelForm

2、字段類型

生成的Form類中將具備和指定的模型字段對應的表單字段,順序爲fields屬性列表中指定的順序。html

每一個模型字段有一個對應的默認表單字段。好比,模型中的CharField表現成表單中的CharField。模型中的ManyToManyField字段會表現成MultipleChoiceField字段。下面是完整的映射列表:數據庫

  • ForeignKey被映射成爲表單類的django.forms.ModelChoiceField,它的選項是一個模型的QuerySet,也就是能夠選擇的對象的列表,可是隻能選擇一個。django

  • ManyToManyField被映射成爲表單類的django.forms.ModelMultipleChoiceField,它的選項也是一個模型的QuerySet,也就是能夠選擇的對象的列表,可是能夠同時選擇多個,多對多嘛。app

  • 若是模型字段設置blank=True,那麼表單字段的required設置爲False。 不然,required=True。
  • 表單字段的label屬性根據模型字段的verbose_name屬性設置,並將第一個字母大寫。
  • 若是模型的某個字段設置了editable=False屬性,那麼它表單類中將不會出現該字段。道理很簡單,都不能編輯了,還放在表單裏提交什麼?
  • 表單字段的help_text設置爲模型字段的help_text
  • 若是模型字段設置了choices參數,那麼表單字段的widget屬性將設置成Select框,其選項來自模型字段的choices。選單中一般會包含一個空選項,而且做爲默認選擇。若是該字段是必選的,它會強制用戶選擇一個選項。 若是模型字段具備default參數,則不會添加空選項到選單中。
模型字段 表單字段
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
相關文章
相關標籤/搜索