Commit d7233e7c authored by Russell Keith-Magee's avatar Russell Keith-Magee
Browse files

Fixed #9932 -- Added a validation error when an inline tries to exclude the...

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
parent 80a54dd2
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -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

+22 −4
Original line number Diff line number Diff line
@@ -4,8 +4,12 @@ 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',)
@@ -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.

"""}