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 | |