From d7233e7c5adb8a885cb7265f58ef8a3baedbf8e7 Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sun, 3 May 2009 13:39:33 +0000 Subject: [PATCH] Fixed #9932 -- Added a validation error when an inline tries to exclude the foreign key that provides the link to the parent model. Thanks to david for the report and patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@10668 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/admin/validation.py | 14 +++++++--- .../admin_validation/models.py | 26 ++++++++++++++++--- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/django/contrib/admin/validation.py b/django/contrib/admin/validation.py index 3243bf86e16..4bef007e6c9 100644 --- a/django/contrib/admin/validation.py +++ b/django/contrib/admin/validation.py @@ -5,7 +5,7 @@ except NameError: from django.core.exceptions import ImproperlyConfigured from django.db import models -from django.forms.models import BaseModelForm, BaseModelFormSet, fields_for_model +from django.forms.models import BaseModelForm, BaseModelFormSet, fields_for_model, _get_foreign_key from django.contrib.admin.options import flatten_fieldsets, BaseModelAdmin from django.contrib.admin.options import HORIZONTAL, VERTICAL @@ -146,9 +146,9 @@ def validate(cls, model): raise ImproperlyConfigured("'%s.inlines[%d].model' does not " "inherit from models.Model." % (cls.__name__, idx)) validate_base(inline, inline.model) - validate_inline(inline) + validate_inline(inline, cls, model) -def validate_inline(cls): +def validate_inline(cls, parent, parent_model): # model is already verified to exist and be a Model if cls.fk_name: # default value is None f = get_field(cls, cls.model, cls.model._meta, 'fk_name', cls.fk_name) @@ -167,6 +167,14 @@ def validate_inline(cls): raise ImproperlyConfigured("'%s.formset' does not inherit from " "BaseModelFormSet." % cls.__name__) + # exclude + if hasattr(cls, 'exclude') and cls.exclude: + fk_name = _get_foreign_key(parent_model, cls.model).name + if fk_name in cls.exclude: + raise ImproperlyConfigured("%s cannot exclude the field " + "'%s' - this is the foreign key to the parent model " + "%s." % (cls.__name__, fk_name, parent_model.__name__)) + def validate_base(cls, model): opts = model._meta diff --git a/tests/regressiontests/admin_validation/models.py b/tests/regressiontests/admin_validation/models.py index bd83f80a1bd..1ff89e25024 100644 --- a/tests/regressiontests/admin_validation/models.py +++ b/tests/regressiontests/admin_validation/models.py @@ -4,12 +4,16 @@ Tests of ModelAdmin validation logic. from django.db import models +class Album(models.Model): + title = models.CharField(max_length=150) + class Song(models.Model): title = models.CharField(max_length=150) - + album = models.ForeignKey(Album) + class Meta: ordering = ('title',) - + def __unicode__(self): return self.title @@ -19,9 +23,7 @@ __test__ = {'API_TESTS':""" >>> from django.contrib import admin >>> from django.contrib.admin.validation import validate -# # Regression test for #8027: custom ModelForms with fields/fieldsets -# >>> class SongForm(forms.ModelForm): ... pass @@ -40,4 +42,20 @@ Traceback (most recent call last): ... ImproperlyConfigured: 'InvalidFields.fields' refers to field 'spam' that is missing from the form. +# Regression test for #9932 - exclude in InlineModelAdmin +# should not contain the ForeignKey field used in ModelAdmin.model + +>>> class SongInline(admin.StackedInline): +... model = Song +... exclude = ['album'] + +>>> class AlbumAdmin(admin.ModelAdmin): +... model = Album +... inlines = [SongInline] + +>>> validate(AlbumAdmin, Album) +Traceback (most recent call last): + ... +ImproperlyConfigured: SongInline cannot exclude the field 'album' - this is the foreign key to the parent model Album. + """}