Forms#3

ModelForm

以已创建的model为原型创建表单时可以继承forms.ModelForm
大多数model的字段类型都有对应的form字段类型,除了几个比较特殊的字段

  • ForeignKey这个model字段对应着form字段中的ModelChoiceField(其是一个ChoiceField)
  • ManyToManyField字段则对应着form字段中的ModelMultipleChoiceField(其是一个MutipleChoiceField)

form字段中的一些其它属性:

  • 如果在model fieldblank=True,在form field中会有required=False
  • form field的标签名将会默认为model field中的verbose_name
  • model field中的help_text属性将会被form field使用
  • 如果model field中存在choices参数,form field中将会设置widget=Select
from django.db import models
from django.forms import ModelForm

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)

class AuthorForm(ModelForm):
    # 在Meta中指定对应的model和会在表单中可见的字段
    # 可以在Meta中重载error_messages
    class Meta:
        model = Author
        fields = ['name', 'title', 'birth_date']

class BookForm(ModelForm):
    class Meta:
        model = Book
        fields = ['name', 'authors']

上边的ModelForm基本上等同于下边自定义的Form(除了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())

save()方法

ModelForm中有一个save()方法,该方法会将表单提交的数据保存到数据库中,并返回一个model实例

commit关键字参数
commit参数默认为True,即会自动将表单数据保存入数据库中;
若将commit设置为False,只会得到一个model实例,而不会向数据库提交,如果需要提交,则利用model实例的save()方法进行提交;
需要注意的一点是,当model与其他Model存在many-to-many关系时,若设置commit=False,则在对model实例进行save()后,还需要对表单调用save_m2m()方法以提交many-to-many表中的数据

# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)

# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)

# Modify the author in some way.
>>> new_author.some_field = 'some_value'

# Save the new instance.
>>> new_author.save()

# Now, save the many-to-many data for the form.
>>> f.save_m2m()

选择使用的字段

官方推荐通过fields来显式地指定需要提交的表单字段,以保证表单提交过程中的安全
设置field属性的两种快捷方法

  • 使用__all__来声明使用所有的字段
    from django.forms import ModelForm
    
    class AuthorForm(ModelForm):
        class Meta:
            model = Author
            fields = '__all__'
    
  • 设置exclude属性来声明不会使用的字段
    class PartialAuthorForm(ModelForm):
        class Meta:
            model = Author
            exclude = ['title']
    

重载model中的字段

可以在ModelForm中改变model字段在表单中的表现形式

from django.forms import ModelForm, Textarea
from myapp.models import Author

class AuthorForm(ModelForm):
    class Meta:
        model = Author
        fields = ('name', 'title', 'birth_date')
        # 将model中name列的表现形式由text变为textarea,并指定一些属性
        widgets = {
            'name': Textarea(attrs={'cols': 80, 'rows': 20}),
        }

除此之外,还可以在Meta中重新指定label, help_texterror_messages属性

from django.utils.translation import ugettext_lazy as _

class AuthorForm(ModelForm):
    class Meta:
        model = Author
        fields = ('name', 'title', 'birth_date')
        # 通过字典来改变属性(键为需要改变的列名)
        labels = {
            'name': _('Writer'),
        }
        help_texts = {
            'name': _('Some useful help text.'),
        }
        error_messages = {
            'name': {
                'max_length': _("This writer's name is too long."),
            },
        }

Form Asset

在Media中设置css, js

你可能感兴趣的:(Forms#3)