Django组件-ModelForm

Posted bubu99

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django组件-ModelForm相关的知识,希望对你有一定的参考价值。

模型表单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的主要内容,如果未能解决你的问题,请参考以下文章

Django 组件-ModelForm

Django之modelform组件

Django组件-ModelForm

Django之ModelForm组件

Django之ModelForm组件

Django之ModelForm组件