From be9376d9ad7ef6435867fdcbce2b1bf80973c8cf Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Thu, 19 Nov 2009 15:07:42 +0000 Subject: [PATCH] =?UTF-8?q?Corrected=20a=20regression=20in=20validation=20?= =?UTF-8?q?of=20admin=20fieldsets=20with=20nested=20definitions=20from=20r?= =?UTF-8?q?11744.=20Thanks=20to=20Davor=20Lu=C4=8Di=C4=87=20for=20the=20re?= =?UTF-8?q?port.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://code.djangoproject.com/svn/django/trunk@11752 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/admin/validation.py | 31 +++++++++++-------- .../admin_validation/models.py | 9 ++++++ 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/django/contrib/admin/validation.py b/django/contrib/admin/validation.py index 47b70a72db..726da650a6 100644 --- a/django/contrib/admin/validation.py +++ b/django/contrib/admin/validation.py @@ -219,19 +219,24 @@ def validate_base(cls, model): raise ImproperlyConfigured("'fields' key is required in " "%s.fieldsets[%d][1] field options dict." % (cls.__name__, idx)) - for field in fieldset[1]['fields']: - check_formfield(cls, model, opts, "fieldsets[%d][1]['fields']" % idx, field) - try: - f = opts.get_field(field) - if isinstance(f, models.ManyToManyField) and not f.rel.through._meta.auto_created: - raise ImproperlyConfigured("'%s.fieldsets[%d][1]['fields']' " - "can't include the ManyToManyField field '%s' because " - "'%s' manually specifies a 'through' model." % ( - cls.__name__, idx, field, field)) - except models.FieldDoesNotExist: - # If we can't find a field on the model that matches, - # it could be an extra field on the form. - pass + for fields in fieldset[1]['fields']: + # The entry in fields might be a tuple. If it is a standalone + # field, make it into a tuple to make processing easier. + if type(fields) != tuple: + fields = (fields,) + for field in fields: + check_formfield(cls, model, opts, "fieldsets[%d][1]['fields']" % idx, field) + try: + f = opts.get_field(field) + if isinstance(f, models.ManyToManyField) and not f.rel.through._meta.auto_created: + raise ImproperlyConfigured("'%s.fieldsets[%d][1]['fields']' " + "can't include the ManyToManyField field '%s' because " + "'%s' manually specifies a 'through' model." % ( + cls.__name__, idx, field, field)) + except models.FieldDoesNotExist: + # If we can't find a field on the model that matches, + # it could be an extra field on the form. + pass flattened_fieldsets = flatten_fieldsets(cls.fieldsets) if len(flattened_fieldsets) > len(set(flattened_fieldsets)): raise ImproperlyConfigured('There are duplicate field(s) in %s.fieldsets' % cls.__name__) diff --git a/tests/regressiontests/admin_validation/models.py b/tests/regressiontests/admin_validation/models.py index 1a34e4d30c..eb53a9dd6e 100644 --- a/tests/regressiontests/admin_validation/models.py +++ b/tests/regressiontests/admin_validation/models.py @@ -32,6 +32,8 @@ class Author(models.Model): class Book(models.Model): name = models.CharField(max_length=100) + subtitle = models.CharField(max_length=100) + price = models.FloatField() authors = models.ManyToManyField(Author, through='AuthorsBooks') @@ -131,6 +133,13 @@ Traceback (most recent call last): ... ImproperlyConfigured: 'FieldsetBookAdmin.fieldsets[1][1]['fields']' can't include the ManyToManyField field 'authors' because 'authors' manually specifies a 'through' model. +>>> class NestedFieldsetAdmin(admin.ModelAdmin): +... fieldsets = ( +... ('Main', {'fields': ('price', ('name', 'subtitle'))}), +... ) + +>>> validate(NestedFieldsetAdmin, Book) + # Regression test for #12209 -- If the explicitly provided through model # is specified as a string, the admin should still be able use # Model.m2m_field.through