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
相关文章
相关标签/搜索