~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to tests/admin_validation/tests.py

  • Committer: Package Import Robot
  • Author(s): Luke Faraone
  • Date: 2013-11-07 15:33:49 UTC
  • mfrom: (1.3.12)
  • Revision ID: package-import@ubuntu.com-20131107153349-e31sc149l2szs3jb
Tags: 1.6-1
* New upstream version. Closes: #557474, #724637.
* python-django now also suggests the installation of ipython,
  bpython, python-django-doc, and libgdal1.
  Closes: #636511, #686333, #704203
* Set package maintainer to Debian Python Modules Team.
* Bump standards version to 3.9.5, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from __future__ import absolute_import
 
2
 
 
3
from django import forms
 
4
from django.contrib import admin
 
5
from django.core.exceptions import ImproperlyConfigured
 
6
from django.test import TestCase
 
7
 
 
8
from .models import Song, Book, Album, TwoAlbumFKAndAnE, State, City
 
9
 
 
10
 
 
11
class SongForm(forms.ModelForm):
 
12
    pass
 
13
 
 
14
class ValidFields(admin.ModelAdmin):
 
15
    form = SongForm
 
16
    fields = ['title']
 
17
 
 
18
class ValidFormFieldsets(admin.ModelAdmin):
 
19
    def get_form(self, request, obj=None, **kwargs):
 
20
        class ExtraFieldForm(SongForm):
 
21
            name = forms.CharField(max_length=50)
 
22
        return ExtraFieldForm
 
23
 
 
24
    fieldsets = (
 
25
        (None, {
 
26
            'fields': ('name',),
 
27
        }),
 
28
    )
 
29
 
 
30
class ValidationTestCase(TestCase):
 
31
 
 
32
    def test_readonly_and_editable(self):
 
33
        class SongAdmin(admin.ModelAdmin):
 
34
            readonly_fields = ["original_release"]
 
35
            fieldsets = [
 
36
                (None, {
 
37
                    "fields": ["title", "original_release"],
 
38
                }),
 
39
            ]
 
40
        SongAdmin.validate(Song)
 
41
 
 
42
    def test_custom_modelforms_with_fields_fieldsets(self):
 
43
        """
 
44
        # Regression test for #8027: custom ModelForms with fields/fieldsets
 
45
        """
 
46
        ValidFields.validate(Song)
 
47
 
 
48
    def test_custom_get_form_with_fieldsets(self):
 
49
        """
 
50
        Ensure that the fieldsets validation is skipped when the ModelAdmin.get_form() method
 
51
        is overridden.
 
52
        Refs #19445.
 
53
        """
 
54
        ValidFormFieldsets.validate(Song)
 
55
 
 
56
    def test_exclude_values(self):
 
57
        """
 
58
        Tests for basic validation of 'exclude' option values (#12689)
 
59
        """
 
60
        class ExcludedFields1(admin.ModelAdmin):
 
61
            exclude = ('foo')
 
62
        self.assertRaisesMessage(ImproperlyConfigured,
 
63
            "'ExcludedFields1.exclude' must be a list or tuple.",
 
64
            ExcludedFields1.validate,
 
65
            Book)
 
66
 
 
67
    def test_exclude_duplicate_values(self):
 
68
        class ExcludedFields2(admin.ModelAdmin):
 
69
            exclude = ('name', 'name')
 
70
        self.assertRaisesMessage(ImproperlyConfigured,
 
71
            "There are duplicate field(s) in ExcludedFields2.exclude",
 
72
            ExcludedFields2.validate,
 
73
            Book)
 
74
 
 
75
    def test_exclude_in_inline(self):
 
76
        class ExcludedFieldsInline(admin.TabularInline):
 
77
            model = Song
 
78
            exclude = ('foo')
 
79
 
 
80
        class ExcludedFieldsAlbumAdmin(admin.ModelAdmin):
 
81
            model = Album
 
82
            inlines = [ExcludedFieldsInline]
 
83
 
 
84
        self.assertRaisesMessage(ImproperlyConfigured,
 
85
            "'ExcludedFieldsInline.exclude' must be a list or tuple.",
 
86
            ExcludedFieldsAlbumAdmin.validate,
 
87
            Album)
 
88
 
 
89
    def test_exclude_inline_model_admin(self):
 
90
        """
 
91
        # Regression test for #9932 - exclude in InlineModelAdmin
 
92
        # should not contain the ForeignKey field used in ModelAdmin.model
 
93
        """
 
94
        class SongInline(admin.StackedInline):
 
95
            model = Song
 
96
            exclude = ['album']
 
97
 
 
98
        class AlbumAdmin(admin.ModelAdmin):
 
99
            model = Album
 
100
            inlines = [SongInline]
 
101
 
 
102
        self.assertRaisesMessage(ImproperlyConfigured,
 
103
            "SongInline cannot exclude the field 'album' - this is the foreign key to the parent model admin_validation.Album.",
 
104
            AlbumAdmin.validate,
 
105
            Album)
 
106
 
 
107
    def test_app_label_in_admin_validation(self):
 
108
        """
 
109
        Regression test for #15669 - Include app label in admin validation messages
 
110
        """
 
111
        class RawIdNonexistingAdmin(admin.ModelAdmin):
 
112
            raw_id_fields = ('nonexisting',)
 
113
 
 
114
        self.assertRaisesMessage(ImproperlyConfigured,
 
115
            "'RawIdNonexistingAdmin.raw_id_fields' refers to field 'nonexisting' that is missing from model 'admin_validation.Album'.",
 
116
            RawIdNonexistingAdmin.validate,
 
117
            Album)
 
118
 
 
119
    def test_fk_exclusion(self):
 
120
        """
 
121
        Regression test for #11709 - when testing for fk excluding (when exclude is
 
122
        given) make sure fk_name is honored or things blow up when there is more
 
123
        than one fk to the parent model.
 
124
        """
 
125
        class TwoAlbumFKAndAnEInline(admin.TabularInline):
 
126
            model = TwoAlbumFKAndAnE
 
127
            exclude = ("e",)
 
128
            fk_name = "album1"
 
129
        class MyAdmin(admin.ModelAdmin):
 
130
            inlines = [TwoAlbumFKAndAnEInline]
 
131
        MyAdmin.validate(Album)
 
132
 
 
133
 
 
134
    def test_inline_self_validation(self):
 
135
        class TwoAlbumFKAndAnEInline(admin.TabularInline):
 
136
            model = TwoAlbumFKAndAnE
 
137
        class MyAdmin(admin.ModelAdmin):
 
138
            inlines = [TwoAlbumFKAndAnEInline]
 
139
 
 
140
        self.assertRaisesMessage(Exception,
 
141
            "<class 'admin_validation.models.TwoAlbumFKAndAnE'> has more than 1 ForeignKey to <class 'admin_validation.models.Album'>",
 
142
            MyAdmin.validate, Album)
 
143
 
 
144
    def test_inline_with_specified(self):
 
145
        class TwoAlbumFKAndAnEInline(admin.TabularInline):
 
146
            model = TwoAlbumFKAndAnE
 
147
            fk_name = "album1"
 
148
 
 
149
        class MyAdmin(admin.ModelAdmin):
 
150
            inlines = [TwoAlbumFKAndAnEInline]
 
151
        MyAdmin.validate(Album)
 
152
 
 
153
    def test_readonly(self):
 
154
        class SongAdmin(admin.ModelAdmin):
 
155
            readonly_fields = ("title",)
 
156
 
 
157
        SongAdmin.validate(Song)
 
158
 
 
159
    def test_readonly_on_method(self):
 
160
        def my_function(obj):
 
161
            pass
 
162
 
 
163
        class SongAdmin(admin.ModelAdmin):
 
164
            readonly_fields = (my_function,)
 
165
 
 
166
        SongAdmin.validate(Song)
 
167
 
 
168
    def test_readonly_on_modeladmin(self):
 
169
        class SongAdmin(admin.ModelAdmin):
 
170
            readonly_fields = ("readonly_method_on_modeladmin",)
 
171
 
 
172
            def readonly_method_on_modeladmin(self, obj):
 
173
                pass
 
174
 
 
175
        SongAdmin.validate(Song)
 
176
 
 
177
    def test_readonly_method_on_model(self):
 
178
        class SongAdmin(admin.ModelAdmin):
 
179
            readonly_fields = ("readonly_method_on_model",)
 
180
 
 
181
        SongAdmin.validate(Song)
 
182
 
 
183
    def test_nonexistant_field(self):
 
184
        class SongAdmin(admin.ModelAdmin):
 
185
            readonly_fields = ("title", "nonexistant")
 
186
 
 
187
        self.assertRaisesMessage(ImproperlyConfigured,
 
188
            "SongAdmin.readonly_fields[1], 'nonexistant' is not a callable or an attribute of 'SongAdmin' or found in the model 'Song'.",
 
189
            SongAdmin.validate,
 
190
            Song)
 
191
 
 
192
    def test_nonexistant_field_on_inline(self):
 
193
        class CityInline(admin.TabularInline):
 
194
            model = City
 
195
            readonly_fields=['i_dont_exist'] # Missing attribute
 
196
 
 
197
        self.assertRaisesMessage(ImproperlyConfigured,
 
198
            "CityInline.readonly_fields[0], 'i_dont_exist' is not a callable or an attribute of 'CityInline' or found in the model 'City'.",
 
199
            CityInline.validate,
 
200
            City)
 
201
 
 
202
    def test_extra(self):
 
203
        class SongAdmin(admin.ModelAdmin):
 
204
            def awesome_song(self, instance):
 
205
                if instance.title == "Born to Run":
 
206
                    return "Best Ever!"
 
207
                return "Status unknown."
 
208
        SongAdmin.validate(Song)
 
209
 
 
210
    def test_readonly_lambda(self):
 
211
        class SongAdmin(admin.ModelAdmin):
 
212
            readonly_fields = (lambda obj: "test",)
 
213
 
 
214
        SongAdmin.validate(Song)
 
215
 
 
216
    def test_graceful_m2m_fail(self):
 
217
        """
 
218
        Regression test for #12203/#12237 - Fail more gracefully when a M2M field that
 
219
        specifies the 'through' option is included in the 'fields' or the 'fieldsets'
 
220
        ModelAdmin options.
 
221
        """
 
222
 
 
223
        class BookAdmin(admin.ModelAdmin):
 
224
            fields = ['authors']
 
225
 
 
226
        self.assertRaisesMessage(ImproperlyConfigured,
 
227
            "'BookAdmin.fields' can't include the ManyToManyField field 'authors' because 'authors' manually specifies a 'through' model.",
 
228
            BookAdmin.validate,
 
229
            Book)
 
230
 
 
231
    def test_cannot_include_through(self):
 
232
        class FieldsetBookAdmin(admin.ModelAdmin):
 
233
            fieldsets = (
 
234
                ('Header 1', {'fields': ('name',)}),
 
235
                ('Header 2', {'fields': ('authors',)}),
 
236
            )
 
237
        self.assertRaisesMessage(ImproperlyConfigured,
 
238
            "'FieldsetBookAdmin.fieldsets[1][1]['fields']' can't include the ManyToManyField field 'authors' because 'authors' manually specifies a 'through' model.",
 
239
            FieldsetBookAdmin.validate,
 
240
            Book)
 
241
 
 
242
    def test_nested_fields(self):
 
243
        class NestedFieldsAdmin(admin.ModelAdmin):
 
244
           fields = ('price', ('name', 'subtitle'))
 
245
        NestedFieldsAdmin.validate(Book)
 
246
 
 
247
    def test_nested_fieldsets(self):
 
248
        class NestedFieldsetAdmin(admin.ModelAdmin):
 
249
           fieldsets = (
 
250
               ('Main', {'fields': ('price', ('name', 'subtitle'))}),
 
251
           )
 
252
        NestedFieldsetAdmin.validate(Book)
 
253
 
 
254
    def test_explicit_through_override(self):
 
255
        """
 
256
        Regression test for #12209 -- If the explicitly provided through model
 
257
        is specified as a string, the admin should still be able use
 
258
        Model.m2m_field.through
 
259
        """
 
260
 
 
261
        class AuthorsInline(admin.TabularInline):
 
262
            model = Book.authors.through
 
263
 
 
264
        class BookAdmin(admin.ModelAdmin):
 
265
            inlines = [AuthorsInline]
 
266
 
 
267
        # If the through model is still a string (and hasn't been resolved to a model)
 
268
        # the validation will fail.
 
269
        BookAdmin.validate(Book)
 
270
 
 
271
    def test_non_model_fields(self):
 
272
        """
 
273
        Regression for ensuring ModelAdmin.fields can contain non-model fields
 
274
        that broke with r11737
 
275
        """
 
276
        class SongForm(forms.ModelForm):
 
277
            extra_data = forms.CharField()
 
278
 
 
279
        class FieldsOnFormOnlyAdmin(admin.ModelAdmin):
 
280
            form = SongForm
 
281
            fields = ['title', 'extra_data']
 
282
 
 
283
        FieldsOnFormOnlyAdmin.validate(Song)
 
284
 
 
285
    def test_non_model_first_field(self):
 
286
        """
 
287
        Regression for ensuring ModelAdmin.field can handle first elem being a
 
288
        non-model field (test fix for UnboundLocalError introduced with r16225).
 
289
        """
 
290
        class SongForm(forms.ModelForm):
 
291
            extra_data = forms.CharField()
 
292
            class Meta:
 
293
                model = Song
 
294
                fields = '__all__'
 
295
 
 
296
 
 
297
        class FieldsOnFormOnlyAdmin(admin.ModelAdmin):
 
298
            form = SongForm
 
299
            fields = ['extra_data', 'title']
 
300
 
 
301
        FieldsOnFormOnlyAdmin.validate(Song)