Django:如何显示内联表单集中每个模型对象的表单错误

Posted

技术标签:

【中文标题】Django:如何显示内联表单集中每个模型对象的表单错误【英文标题】:Django: how to display form errors for each model object in a inline formset 【发布时间】:2012-03-15 05:49:38 【问题描述】:

我有一个作者模型和一个书籍模型。用户可以修改给定作者的所有书籍的属性。我希望能够显示每本书的错误,而不是将所有错误都列在顶部,我该怎么做?

模型

from django.db import models
from django.forms import ModelForm, Textarea
from django import forms

class Author(models.Model):
    fname = models.CharField(max_length=100)
    lname = models.CharField(max_length=100)
    def fullname(self):
        return '%s %s' % (self.fname, self.lname)
    fullname = property(fullname)
    def __unicode__(self):
        return self.fullname

class Books(models.Model):
    author = models.ForeignKey(Author)
    title = models.CharField(max_length=50)
    publisher = models.CharField(max_length=50)
    edition = models.CharField(max_length=50)
    comment = models.TextField()
    def __unicode__(self):
         return self.title

查看

def author_books_edit(request, author_id):
    a = get_object_or_404(Author, pk=author_id)
    authorsbooks = a.books_set.all()
    bookformset = inlineformset_factory(Author, Books, can_delete=True, can_order=True, exclude=('company',), extra=1)
    formset = bookformset(instance=a)
    if request.method == "POST":
        formset = bookformset(request.POST, request.FILES, instance=a)
        if formset.is_valid():
            formset.save()
        else:
            form_errors = formset.errors
            return render_to_response('test/authors_books_edits.html', 'author': a, 'authorsbooks': authorsbooks, 'formset': formset, 'form_errors': form_errors, context_instance=RequestContext(request))
    return render_to_response('test/authors_books_edits.html', 'author': a, 'authorsbooks': authorsbooks, 'formset': formset,, context_instance=RequestContext(request))

模板

#all errors are here
% for dict in form_errors %
     dict 
% endfor %

#all forms are here, i want to pair the errors for each form
<form method="post" action="/test/ author.id /books/">
    % csrf_token %
        <table>
         formset 
        </table>
    <input type="submit" value="Submit"/>
    </form>

更新的模板:不显示错误

<form method="post" action="/test/ author.id /books/">
    % formset.management_form %
    % csrf_token %
    <table>
        % for x in formset %
        x.errors 
         x 
        % endfor %
    </table>
<input type="submit" value="Submit"/>

【问题讨论】:

您可以添加书籍和作者模型的来源以便我可以尝试吗?谢谢;) "get_object_or_404(author, pk=author_id)" 应该是 "get_object_or_404(Author, pk=author_id)" (大写的作者)对吗?另外,您确定您的模型名为 Book 吗?看起来应该是书籍? also: aurthorsbooks 应该是 authorsbooks 是的,对不起,我正在复制但掩盖了一些变量。无论如何,结构本质上是相同的。并且仍然看不到错误..除了使用时:% for dict in form_errors % dict % endfor % 你能显示你想要的结果的伪html吗?我不太确定是否理解“我想为每个表单配对错误” 【参考方案1】:

编辑

authors_books_edits.html

<form method="post" action="/test/ author.id /books/">
    % csrf_token %
     formset.management_form 
    % for form in formset.forms %
         form.non_field_errors 
         form.errors 
        <table>
             form.as_table 
        </table>
    % endfor %
    <input type="submit" value="Submit"/>
</form>

views.py

from django.shortcuts import *
from django.forms.models import inlineformset_factory

from .models import *

def author_books_edit(request, author_id):
    a = get_object_or_404(Author, pk=author_id)
    authorsbooks = a.books_set.all()
    bookformset = inlineformset_factory(Author, Books, can_delete=True, can_order=True, exclude=('company',), extra=1)
    formset = bookformset(instance=a)
    if request.method == "POST":
        formset = bookformset(request.POST, request.FILES, instance=a)
        if formset.is_valid():
            formset.save()
        else:
            form_errors = formset.errors
            return render_to_response('authors_books_edits.html', 'author': a, 'authorsbooks': authorsbooks, 'formset': formset, 'form_errors': form_errors, context_instance=RequestContext(request))
    return render_to_response('authors_books_edits.html', 'author': a, 'authorsbooks': authorsbooks, 'formset': formset,, context_instance=RequestContext(request))

models.py

from django.db import models

class Author(models.Model):
    fname = models.CharField(max_length=100)
    lname = models.CharField(max_length=100)
    def fullname(self):
        return '%s %s' % (self.fname, self.lname)
    fullname = property(fullname)
    def __unicode__(self):
        return self.fullname

class Books(models.Model):
    author = models.ForeignKey(Author)
    title = models.CharField(max_length=50)
    publisher = models.CharField(max_length=50)
    edition = models.CharField(max_length=50)
    comment = models.TextField()
    def __unicode__(self):
         return self.title

urls.py

from django.conf.urls.defaults import patterns, include, url

urlpatterns = patterns('testapp.views',
    url(r'test/(?P<author_id>\d+)/books/$', 'author_books_edit'),
)

您可以制作另一个临时应用来测试它。

看起来像这样:http://imageshack.us/photo/my-images/824/screenshotat20120227190.png/

== 结束编辑

您可以像这样迭代表单:

% for form in formset.forms %
    form 
% endfor %

在这种情况下,请参阅 Django 使用模板文档显示表单:https://docs.djangoproject.com/en/dev/topics/forms/#displaying-a-form-using-a-template

然后,更有趣的是,自定义表单模板(请参阅 form.non_field_errors): https://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template

【讨论】:

由于某种原因我的错误仍然没有出现。我已经更新了我的模板。我做错了什么? 你试过 x.non_field_errors 而不是 x.errors 吗? 是的,x.non_field_errors 没有显示任何内容。这很奇怪,因为 % for dict in form_errors % dict % endfor % 显示错误,只是与我的表单不成对... 错误有两种:字段错误和非字段错误。要获取应显示在输入旁边的字段错误,请使用 form.field_name.errors 。要获取应显示在表单顶部的非字段错误,请调用 form.non_field_errors 感谢您的输入,但仍然没有出现错误。我把 form.non_field_errors 放在 form.management_form 下,我也把 x.nameofmyfield.errors 就在 x 上方,没有任何显示..我做错了什么?这让我发疯了。【参考方案2】:

假设这本书是一种你可以做到的形式:

% for b in authorsbooks %
    b.errors
% endfor %

【讨论】:

我更新了我的模板,但现在我收到一个错误并且页面已损坏...我已更新我的帖子以包含更新的模板。 调试输出说了什么? 它说 ValidationError [u'ManagementForm 数据丢失或已被篡改'] 这是因为:docs.djangoproject.com/en/dev/topics/forms/formsets/…

以上是关于Django:如何显示内联表单集中每个模型对象的表单错误的主要内容,如果未能解决你的问题,请参考以下文章

如何在字段集中显示Django管理员内联模型?

如何使用 django-extra-views 将请求传递到内联表单集中

如果引发 ValidationError,删除链接会在 Django 管理内联表单集中消失

如何在 Django 的表单中拥有嵌套的内联表单集?

有没有办法在 Django 中为内联管理表单设置单独的页面?

在内联表单集中使用 Django FileField