问题
I have a author model and a books model. A user can modify properties of all the books from a given author. I want to be able to display errors for each individual book rather than have all the errors listed on the top, How can I do this?
MODELS
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
VIEW
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))
TEMPLATE
#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>
UPDATED TEMPLATE: doesn't display errors
<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"/>
回答1:
EDIT
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'),
)
You can make another temporary app to test it.
It looks like this: http://imageshack.us/photo/my-images/824/screenshotat20120227190.png/
== END EDIT
You can iterate over forms as such:
{% for form in formset.forms %}
{{ form }}
{% endfor %}
In that case, refer to Django's displaying a form using a template documentation: https://docs.djangoproject.com/en/dev/topics/forms/#displaying-a-form-using-a-template
Then, more interesting, customizing a form template (see form.non_field_errors): https://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template
回答2:
Assuming the book is a form you could do:
{% for b in authorsbooks %}
{{b.errors}}
{% endfor %}
来源:https://stackoverflow.com/questions/9436504/django-how-to-display-form-errors-for-each-model-object-in-a-inline-formset