或者< ul>元素
当然,我们也可以手动的渲染字段。
{{ form.non_field_errors }}
{{ form.subject.errors }}
{{ form.subject }}
{{ form.message.errors }}
{{ form.message }}
{{ form.sender.errors }}
{{ form.sender }}
{{ form.cc_myself.errors }}
{{ form.cc_myself }}
也可以循环逐个的渲染
{% for field in form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
{{ field.help_text|safe }}
{% endif %}
{% endfor %}
7.Further topics
7.1 Formset
formset是一个抽象层,用于在同一页面上处理多个表单.举例:
>>> from django import forms
>>> class ArticleForm(forms.Form):
... title = forms.CharField()
... pub_date = forms.DateField()
您可能希望允许用户同时创建几篇文章.如下:
>>> from django.forms import formset_factory
>>> ArticleFormSet = formset_factory(ArticleForm)
ArticleFormSet就是一个formset.你可以利用它迭代其中的表单展示给用户。
>>> formset = ArticleFormSet()
>>> for form in formset:
... print(form.as_table())
所显示的空表单的数量由extra的参数,默认值为1.下面会展示两个空的表单
>>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
>>> import datetime
>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
>>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
>>> formset = ArticleFormSet(initial=[
... {'title': 'Django is now open source',
... 'pub_date': datetime.date.today(),}
... ])
>>> for form in formset:
... print(form.as_table())
上面会展示三组表单,其中第一组表单会默认填充initial数据,另外两组表单为空。
对formsetfactory()的maxnum参数提供了限制将显示表单的数量的能力。
>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
>>> ArticleFormSet = formset_factory(ArticleForm, extra=2, max_num=1)
>>> formset = ArticleFormSet()
>>> for form in formset:
... print(form.as_table())
7.2 验证
对Formset的验证与常规表单几乎相同.在formset上有一个is_valid的方法 提供一种方便的方式来验证表单中的所有表单:
>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
>>> ArticleFormSet = formset_factory(ArticleForm)
>>> data = {
... 'form-TOTAL_FORMS': '1',
... 'form-INITIAL_FORMS': '0',
... 'form-MAX_NUM_FORMS': '',
... }
>>> formset = ArticleFormSet(data)
>>> formset.is_valid()
True
您可能已经注意到额外的数据(form-TOTAL_FORMS, form-INITIAL_FORMS和form-MAX_NUM_FORMS)在上面的formset的数据中是必需的。如果不提供此管理数据,则会出现异常.
>>> data = {
... 'form-0-title': 'Test',
... 'form-0-pub_date': '',
... }
>>> formset = ArticleFormSet(data)
>>> formset.is_valid()
Traceback (most recent call last):
...
django.forms.utils.ValidationError: ['ManagementForm data is missing or has been tampered with']
7.3 定制formset validation
formset 有和Form 类相似的clean方法,该方法可用来定义你自己在formset水平上的验证。举例:
>>> from django.forms import BaseFormSet
>>> from django.forms import formset_factory
>>> from myapp.forms import ArticleForm
>>> class BaseArticleFormSet(BaseFormSet):
... def clean(self):
... """Checks that no two articles have the same title."""
... if any(self.errors):
... # Don't bother validating the formset unless each form is valid on its own
... return
... titles = []
... for form in self.forms:
... title = form.cleaned_data['title']
... if title in titles:
... raise forms.ValidationError("Articles in a set must have distinct titles.")
... titles.append(title)
>>> ArticleFormSet = formset_factory(ArticleForm, formset=BaseArticleFormSet)
>>> data = {
... 'form-TOTAL_FORMS': '2',
... 'form-INITIAL_FORMS': '0',
... 'form-MAX_NUM_FORMS': '',
... 'form-0-title': 'Test',
... 'form-0-pub_date': '1904-06-16',
... 'form-1-title': 'Test',
... 'form-1-pub_date': '1912-06-23',
... }
>>> formset = ArticleFormSet(data)
>>> formset.is_valid()
False
>>> formset.errors
[{}, {}]
>>> formset.non_form_errors()
['Articles in a set must have distinct titles.']
formset的clean方法在所有的form的clean方法调用之后调用,所有爆出的错误都可以用non_form_errors()方法看到。
8.Creating forms from models
8.1 ModelForm
如果你正在构建一个数据库驱动的应用程序,那么你可能会有与Django models密切相关的Form.举例:
>>> from django.forms import ModelForm
>>> from myapp.models import Article
# Create the form class.
>>> class ArticleForm(ModelForm):
... class Meta:
... model = Article
... fields = ['pub_date', 'headline', 'content', 'reporter']
# Creating a form to add an article.
>>> form = ArticleForm()
# Creating a form to change an existing article.
>>> article = Article.objects.get(pk=1)
>>> form = ArticleForm(instance=article)
8.2 Field types
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):
class Meta:
model = Author
fields = ['name', 'title', 'birth_date']
class BookForm(ModelForm):
class Meta:
model = Book
fields = ['name', 'authors']
上面的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())
8.3 The save() method
>>> from myapp.models import Article
>>> from myapp.forms import ArticleForm
# Create a form instance from POST data.
>>> f = ArticleForm(request.POST)
# Save a new Article object from the form's data.
>>> new_article = f.save()
# Create a form to edit an existing Article, but use
# POST data to populate the form.
>>> a = Article.objects.get(pk=1)
>>> f = ArticleForm(request.POST, instance=a)
>>> f.save()
需要注意的是:
# 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()
当我们以commit=False的形式调用save方法后,数据不会保存到数据库中,我们还可以对其中的数据字段进行修改,再次调用save()才会保存到数据库中,如果表单中含有many_to_many类型的字段,为了保存数据还需要调用save_m2m方法。该方法只有在commit=False才需要调用,其他时候无需调用。
另外,django使用下面的规则:如果你在model的字段中设置了editable=False,那么,任何通过ModelForm创建的form都不会包含它。
你可能感兴趣的:(Django Forms 基本总结(一))