diff --git a/django/contrib/admin/validation.py b/django/contrib/admin/validation.py
|
a
|
b
|
|
| 261 | 261 | if len(flattened_fieldsets) > len(set(flattened_fieldsets)): |
| 262 | 262 | raise ImproperlyConfigured('There are duplicate field(s) in %s.fieldsets' % cls.__name__) |
| 263 | 263 | |
| | 264 | # exclude |
| | 265 | if cls.exclude: # default value is None |
| | 266 | check_isseq(cls, 'exclude', cls.exclude) |
| | 267 | for field in cls.exclude: |
| | 268 | check_formfield(cls, model, opts, 'exclude', field) |
| | 269 | try: |
| | 270 | f = opts.get_field(field) |
| | 271 | except models.FieldDoesNotExist: |
| | 272 | # If we can't find a field on the model that matches, |
| | 273 | # it could be an extra field on the form. |
| | 274 | continue |
| | 275 | if len(cls.exclude) > len(set(cls.exclude)): |
| | 276 | raise ImproperlyConfigured('There are duplicate field(s) in %s.exclude' % cls.__name__) |
| 264 | 277 | |
| 265 | 278 | # form |
| 266 | 279 | if hasattr(cls, 'form') and not issubclass(cls.form, BaseModelForm): |
diff --git a/tests/regressiontests/admin_validation/models.py b/tests/regressiontests/admin_validation/models.py
|
a
|
b
|
|
| 71 | 71 | ... |
| 72 | 72 | ImproperlyConfigured: 'InvalidFields.fields' refers to field 'spam' that is missing from the form. |
| 73 | 73 | |
| | 74 | # Tests for basic validation of 'exclude' option values (#12689) |
| | 75 | |
| | 76 | >>> class ExcludedFields1(admin.ModelAdmin): |
| | 77 | ... exclude = ('foo') |
| | 78 | |
| | 79 | >>> validate(ExcludedFields1, Book) |
| | 80 | Traceback (most recent call last): |
| | 81 | ... |
| | 82 | ImproperlyConfigured: 'ExcludedFields1.exclude' must be a list or tuple. |
| | 83 | |
| | 84 | >>> class ExcludedFields2(admin.ModelAdmin): |
| | 85 | ... exclude = ('name', 'name') |
| | 86 | |
| | 87 | >>> validate(ExcludedFields2, Book) |
| | 88 | Traceback (most recent call last): |
| | 89 | ... |
| | 90 | ImproperlyConfigured: There are duplicate field(s) in ExcludedFields2.exclude |
| | 91 | |
| | 92 | >>> class ExcludedFieldsInline(admin.TabularInline): |
| | 93 | ... model = Song |
| | 94 | ... exclude = ('foo') |
| | 95 | |
| | 96 | >>> class ExcludedFieldsAlbumAdmin(admin.ModelAdmin): |
| | 97 | ... model = Album |
| | 98 | ... inlines = [ExcludedFieldsInline] |
| | 99 | |
| | 100 | >>> validate(ExcludedFieldsAlbumAdmin, Album) |
| | 101 | Traceback (most recent call last): |
| | 102 | ... |
| | 103 | ImproperlyConfigured: 'ExcludedFieldsInline.exclude' must be a list or tuple. |
| | 104 | |
| 74 | 105 | # Regression test for #9932 - exclude in InlineModelAdmin |
| 75 | 106 | # should not contain the ForeignKey field used in ModelAdmin.model |
| 76 | 107 | |