17
20
def __unicode__(self):
23
def readonly_method_on_model(self):
28
class TwoAlbumFKAndAnE(models.Model):
29
album1 = models.ForeignKey(Album, related_name="album1_set")
30
album2 = models.ForeignKey(Album, related_name="album2_set")
31
e = models.CharField(max_length=1)
34
class Author(models.Model):
35
name = models.CharField(max_length=100)
38
class Book(models.Model):
39
name = models.CharField(max_length=100)
40
subtitle = models.CharField(max_length=100)
41
price = models.FloatField()
42
authors = models.ManyToManyField(Author, through='AuthorsBooks')
45
class AuthorsBooks(models.Model):
46
author = models.ForeignKey(Author)
47
book = models.ForeignKey(Book)
20
50
__test__ = {'API_TESTS':"""
22
52
>>> from django import forms
23
53
>>> from django.contrib import admin
24
>>> from django.contrib.admin.validation import validate
54
>>> from django.contrib.admin.validation import validate, validate_inline
26
56
# Regression test for #8027: custom ModelForms with fields/fieldsets
43
73
ImproperlyConfigured: 'InvalidFields.fields' refers to field 'spam' that is missing from the form.
75
# Tests for basic validation of 'exclude' option values (#12689)
77
>>> class ExcludedFields1(admin.ModelAdmin):
80
>>> validate(ExcludedFields1, Book)
81
Traceback (most recent call last):
83
ImproperlyConfigured: 'ExcludedFields1.exclude' must be a list or tuple.
85
>>> class ExcludedFields2(admin.ModelAdmin):
86
... exclude = ('name', 'name')
88
>>> validate(ExcludedFields2, Book)
89
Traceback (most recent call last):
91
ImproperlyConfigured: There are duplicate field(s) in ExcludedFields2.exclude
93
>>> class ExcludedFieldsInline(admin.TabularInline):
97
>>> class ExcludedFieldsAlbumAdmin(admin.ModelAdmin):
99
... inlines = [ExcludedFieldsInline]
101
>>> validate(ExcludedFieldsAlbumAdmin, Album)
102
Traceback (most recent call last):
104
ImproperlyConfigured: 'ExcludedFieldsInline.exclude' must be a list or tuple.
45
106
# Regression test for #9932 - exclude in InlineModelAdmin
46
107
# should not contain the ForeignKey field used in ModelAdmin.model
59
120
ImproperlyConfigured: SongInline cannot exclude the field 'album' - this is the foreign key to the parent model Album.
122
# Regression test for #11709 - when testing for fk excluding (when exclude is
123
# given) make sure fk_name is honored or things blow up when there is more
124
# than one fk to the parent model.
126
>>> class TwoAlbumFKAndAnEInline(admin.TabularInline):
127
... model = TwoAlbumFKAndAnE
129
... fk_name = "album1"
131
>>> validate_inline(TwoAlbumFKAndAnEInline, None, Album)
133
# Ensure inlines validate that they can be used correctly.
135
>>> class TwoAlbumFKAndAnEInline(admin.TabularInline):
136
... model = TwoAlbumFKAndAnE
138
>>> validate_inline(TwoAlbumFKAndAnEInline, None, Album)
139
Traceback (most recent call last):
141
Exception: <class 'regressiontests.admin_validation.models.TwoAlbumFKAndAnE'> has more than 1 ForeignKey to <class 'regressiontests.admin_validation.models.Album'>
143
>>> class TwoAlbumFKAndAnEInline(admin.TabularInline):
144
... model = TwoAlbumFKAndAnE
145
... fk_name = "album1"
147
>>> validate_inline(TwoAlbumFKAndAnEInline, None, Album)
149
>>> class SongAdmin(admin.ModelAdmin):
150
... readonly_fields = ("title",)
152
>>> validate(SongAdmin, Song)
154
>>> def my_function(obj):
157
>>> class SongAdmin(admin.ModelAdmin):
158
... readonly_fields = (my_function,)
160
>>> validate(SongAdmin, Song)
162
>>> class SongAdmin(admin.ModelAdmin):
163
... readonly_fields = ("readonly_method_on_modeladmin",)
165
... def readonly_method_on_modeladmin(self, obj):
169
>>> validate(SongAdmin, Song)
171
>>> class SongAdmin(admin.ModelAdmin):
172
... readonly_fields = ("readonly_method_on_model",)
174
>>> validate(SongAdmin, Song)
176
>>> class SongAdmin(admin.ModelAdmin):
177
... readonly_fields = ("title", "nonexistant")
179
>>> validate(SongAdmin, Song)
180
Traceback (most recent call last):
182
ImproperlyConfigured: SongAdmin.readonly_fields[1], 'nonexistant' is not a callable or an attribute of 'SongAdmin' or found in the model 'Song'.
184
>>> class SongAdmin(admin.ModelAdmin):
185
... readonly_fields = ("title", "awesome_song")
186
... fields = ("album", "title", "awesome_song")
188
>>> validate(SongAdmin, Song)
189
Traceback (most recent call last):
191
ImproperlyConfigured: SongAdmin.readonly_fields[1], 'awesome_song' is not a callable or an attribute of 'SongAdmin' or found in the model 'Song'.
193
>>> class SongAdmin(SongAdmin):
194
... def awesome_song(self, instance):
195
... if instance.title == "Born to Run":
196
... return "Best Ever!"
197
... return "Status unknown."
199
>>> validate(SongAdmin, Song)
201
>>> class SongAdmin(admin.ModelAdmin):
202
... readonly_fields = (lambda obj: "test",)
204
>>> validate(SongAdmin, Song)
206
# Regression test for #12203/#12237 - Fail more gracefully when a M2M field that
207
# specifies the 'through' option is included in the 'fields' or the 'fieldsets'
208
# ModelAdmin options.
210
>>> class BookAdmin(admin.ModelAdmin):
211
... fields = ['authors']
213
>>> validate(BookAdmin, Book)
214
Traceback (most recent call last):
216
ImproperlyConfigured: 'BookAdmin.fields' can't include the ManyToManyField field 'authors' because 'authors' manually specifies a 'through' model.
218
>>> class FieldsetBookAdmin(admin.ModelAdmin):
220
... ('Header 1', {'fields': ('name',)}),
221
... ('Header 2', {'fields': ('authors',)}),
224
>>> validate(FieldsetBookAdmin, Book)
225
Traceback (most recent call last):
227
ImproperlyConfigured: 'FieldsetBookAdmin.fieldsets[1][1]['fields']' can't include the ManyToManyField field 'authors' because 'authors' manually specifies a 'through' model.
229
>>> class NestedFieldsetAdmin(admin.ModelAdmin):
231
... ('Main', {'fields': ('price', ('name', 'subtitle'))}),
234
>>> validate(NestedFieldsetAdmin, Book)
236
# Regression test for #12209 -- If the explicitly provided through model
237
# is specified as a string, the admin should still be able use
238
# Model.m2m_field.through
240
>>> class AuthorsInline(admin.TabularInline):
241
... model = Book.authors.through
243
>>> class BookAdmin(admin.ModelAdmin):
244
... inlines = [AuthorsInline]
246
# If the through model is still a string (and hasn't been resolved to a model)
247
# the validation will fail.
248
>>> validate(BookAdmin, Book)
250
# Regression for ensuring ModelAdmin.fields can contain non-model fields
251
# that broke with r11737
253
>>> class SongForm(forms.ModelForm):
254
... extra_data = forms.CharField()
258
>>> class FieldsOnFormOnlyAdmin(admin.ModelAdmin):
260
... fields = ['title', 'extra_data']
262
>>> validate(FieldsOnFormOnlyAdmin, Song)