PageRenderTime 40ms CodeModel.GetById 21ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/regressiontests/admin_widgets/tests.py

https://code.google.com/p/mango-py/
Python | 327 lines | 241 code | 64 blank | 22 comment | 9 complexity | 147462aae275009bc59f32a44edd5f29 MD5 | raw file
  1# encoding: utf-8
  2
  3from datetime import datetime
  4
  5from django import forms
  6from django.conf import settings
  7from django.contrib import admin
  8from django.contrib.admin import widgets
  9from django.contrib.admin.widgets import (FilteredSelectMultiple,
 10    AdminSplitDateTime, AdminFileWidget, ForeignKeyRawIdWidget, AdminRadioSelect,
 11    RelatedFieldWidgetWrapper, ManyToManyRawIdWidget)
 12from django.core.files.storage import default_storage
 13from django.core.files.uploadedfile import SimpleUploadedFile
 14from django.db.models import DateField
 15from django.test import TestCase as DjangoTestCase
 16from django.utils.html import conditional_escape
 17from django.utils.translation import activate, deactivate
 18from django.utils.unittest import TestCase
 19
 20import models
 21
 22
 23class AdminFormfieldForDBFieldTests(TestCase):
 24    """
 25    Tests for correct behavior of ModelAdmin.formfield_for_dbfield
 26    """
 27
 28    def assertFormfield(self, model, fieldname, widgetclass, **admin_overrides):
 29        """
 30        Helper to call formfield_for_dbfield for a given model and field name
 31        and verify that the returned formfield is appropriate.
 32        """
 33        # Override any settings on the model admin
 34        class MyModelAdmin(admin.ModelAdmin):
 35            pass
 36        for k in admin_overrides:
 37            setattr(MyModelAdmin, k, admin_overrides[k])
 38
 39        # Construct the admin, and ask it for a formfield
 40        ma = MyModelAdmin(model, admin.site)
 41        ff = ma.formfield_for_dbfield(model._meta.get_field(fieldname), request=None)
 42
 43        # "unwrap" the widget wrapper, if needed
 44        if isinstance(ff.widget, widgets.RelatedFieldWidgetWrapper):
 45            widget = ff.widget.widget
 46        else:
 47            widget = ff.widget
 48
 49        # Check that we got a field of the right type
 50        self.assertTrue(
 51            isinstance(widget, widgetclass),
 52            "Wrong widget for %s.%s: expected %s, got %s" % \
 53                (model.__class__.__name__, fieldname, widgetclass, type(widget))
 54        )
 55
 56        # Return the formfield so that other tests can continue
 57        return ff
 58
 59    def testDateField(self):
 60        self.assertFormfield(models.Event, 'start_date', widgets.AdminDateWidget)
 61
 62    def testDateTimeField(self):
 63        self.assertFormfield(models.Member, 'birthdate', widgets.AdminSplitDateTime)
 64
 65    def testTimeField(self):
 66        self.assertFormfield(models.Event, 'start_time', widgets.AdminTimeWidget)
 67
 68    def testTextField(self):
 69        self.assertFormfield(models.Event, 'description', widgets.AdminTextareaWidget)
 70
 71    def testURLField(self):
 72        self.assertFormfield(models.Event, 'link', widgets.AdminURLFieldWidget)
 73
 74    def testIntegerField(self):
 75        self.assertFormfield(models.Event, 'min_age', widgets.AdminIntegerFieldWidget)
 76
 77    def testCharField(self):
 78        self.assertFormfield(models.Member, 'name', widgets.AdminTextInputWidget)
 79
 80    def testFileField(self):
 81        self.assertFormfield(models.Album, 'cover_art', widgets.AdminFileWidget)
 82
 83    def testForeignKey(self):
 84        self.assertFormfield(models.Event, 'band', forms.Select)
 85
 86    def testRawIDForeignKey(self):
 87        self.assertFormfield(models.Event, 'band', widgets.ForeignKeyRawIdWidget,
 88                             raw_id_fields=['band'])
 89
 90    def testRadioFieldsForeignKey(self):
 91        ff = self.assertFormfield(models.Event, 'band', widgets.AdminRadioSelect,
 92                                  radio_fields={'band':admin.VERTICAL})
 93        self.assertEqual(ff.empty_label, None)
 94
 95    def testManyToMany(self):
 96        self.assertFormfield(models.Band, 'members', forms.SelectMultiple)
 97
 98    def testRawIDManyTOMany(self):
 99        self.assertFormfield(models.Band, 'members', widgets.ManyToManyRawIdWidget,
100                             raw_id_fields=['members'])
101
102    def testFilteredManyToMany(self):
103        self.assertFormfield(models.Band, 'members', widgets.FilteredSelectMultiple,
104                             filter_vertical=['members'])
105
106    def testFormfieldOverrides(self):
107        self.assertFormfield(models.Event, 'start_date', forms.TextInput,
108                             formfield_overrides={DateField: {'widget': forms.TextInput}})
109
110    def testFieldWithChoices(self):
111        self.assertFormfield(models.Member, 'gender', forms.Select)
112
113    def testChoicesWithRadioFields(self):
114        self.assertFormfield(models.Member, 'gender', widgets.AdminRadioSelect,
115                             radio_fields={'gender':admin.VERTICAL})
116
117    def testInheritance(self):
118        self.assertFormfield(models.Album, 'backside_art', widgets.AdminFileWidget)
119
120
121class AdminFormfieldForDBFieldWithRequestTests(DjangoTestCase):
122    fixtures = ["admin-widgets-users.xml"]
123
124    def testFilterChoicesByRequestUser(self):
125        """
126        Ensure the user can only see their own cars in the foreign key dropdown.
127        """
128        self.client.login(username="super", password="secret")
129        response = self.client.get("/widget_admin/admin_widgets/cartire/add/")
130        self.assertTrue("BMW M3" not in response.content)
131        self.assertTrue("Volkswagon Passat" in response.content)
132
133
134class AdminForeignKeyWidgetChangeList(DjangoTestCase):
135    fixtures = ["admin-widgets-users.xml"]
136    admin_root = '/widget_admin'
137
138    def setUp(self):
139        self.client.login(username="super", password="secret")
140
141    def tearDown(self):
142        self.client.logout()
143
144    def test_changelist_foreignkey(self):
145        response = self.client.get('%s/admin_widgets/car/' % self.admin_root)
146        self.assertTrue('%s/auth/user/add/' % self.admin_root in response.content)
147
148
149class AdminForeignKeyRawIdWidget(DjangoTestCase):
150    fixtures = ["admin-widgets-users.xml"]
151    admin_root = '/widget_admin'
152
153    def setUp(self):
154        self.client.login(username="super", password="secret")
155
156    def tearDown(self):
157        self.client.logout()
158
159    def test_nonexistent_target_id(self):
160        band = models.Band.objects.create(name='Bogey Blues')
161        pk = band.pk
162        band.delete()
163        post_data = {
164            "band": u'%s' % pk,
165        }
166        # Try posting with a non-existent pk in a raw id field: this
167        # should result in an error message, not a server exception.
168        response = self.client.post('%s/admin_widgets/event/add/' % self.admin_root,
169            post_data)
170        self.assertContains(response,
171            'Select a valid choice. That choice is not one of the available choices.')
172
173    def test_invalid_target_id(self):
174
175        for test_str in ('Ińtërnâtiônŕlizćtiřn', "1234'", -1234):
176            # This should result in an error message, not a server exception.
177            response = self.client.post('%s/admin_widgets/event/add/' % self.admin_root,
178                {"band": test_str})
179
180            self.assertContains(response,
181                'Select a valid choice. That choice is not one of the available choices.')
182
183
184class FilteredSelectMultipleWidgetTest(TestCase):
185    def test_render(self):
186        w = FilteredSelectMultiple('test', False)
187        self.assertEqual(
188            conditional_escape(w.render('test', 'test')),
189            '<select multiple="multiple" name="test" class="selectfilter">\n</select><script type="text/javascript">addEvent(window, "load", function(e) {SelectFilter.init("id_test", "test", 0, "%(ADMIN_MEDIA_PREFIX)s"); });</script>\n' % {"ADMIN_MEDIA_PREFIX": settings.ADMIN_MEDIA_PREFIX}
190        )
191
192    def test_stacked_render(self):
193        w = FilteredSelectMultiple('test', True)
194        self.assertEqual(
195            conditional_escape(w.render('test', 'test')),
196            '<select multiple="multiple" name="test" class="selectfilterstacked">\n</select><script type="text/javascript">addEvent(window, "load", function(e) {SelectFilter.init("id_test", "test", 1, "%(ADMIN_MEDIA_PREFIX)s"); });</script>\n' % {"ADMIN_MEDIA_PREFIX": settings.ADMIN_MEDIA_PREFIX}
197        )
198
199
200class AdminSplitDateTimeWidgetTest(TestCase):
201    def test_render(self):
202        w = AdminSplitDateTime()
203        self.assertEqual(
204            conditional_escape(w.render('test', datetime(2007, 12, 1, 9, 30))),
205            '<p class="datetime">Date: <input value="2007-12-01" type="text" class="vDateField" name="test_0" size="10" /><br />Time: <input value="09:30:00" type="text" class="vTimeField" name="test_1" size="8" /></p>',
206        )
207
208    def test_localization(self):
209        w = AdminSplitDateTime()
210
211        activate('de-at')
212        old_USE_L10N = settings.USE_L10N
213        try:
214            settings.USE_L10N = True
215            w.is_localized = True
216            self.assertEqual(
217                conditional_escape(w.render('test', datetime(2007, 12, 1, 9, 30))),
218                '<p class="datetime">Datum: <input value="01.12.2007" type="text" class="vDateField" name="test_0" size="10" /><br />Zeit: <input value="09:30:00" type="text" class="vTimeField" name="test_1" size="8" /></p>',
219            )
220        finally:
221            deactivate()
222            settings.USE_L10N = old_USE_L10N
223
224
225class AdminFileWidgetTest(DjangoTestCase):
226    def test_render(self):
227        band = models.Band.objects.create(name='Linkin Park')
228        album = band.album_set.create(
229            name='Hybrid Theory', cover_art=r'albums\hybrid_theory.jpg'
230        )
231
232        w = AdminFileWidget()
233        self.assertEqual(
234            conditional_escape(w.render('test', album.cover_art)),
235            '<p class="file-upload">Currently: <a href="%(STORAGE_URL)salbums/hybrid_theory.jpg">albums\hybrid_theory.jpg</a> <span class="clearable-file-input"><input type="checkbox" name="test-clear" id="test-clear_id" /> <label for="test-clear_id">Clear</label></span><br />Change: <input type="file" name="test" /></p>' % { 'STORAGE_URL': default_storage.url('') },
236        )
237
238        self.assertEqual(
239            conditional_escape(w.render('test', SimpleUploadedFile('test', 'content'))),
240            '<input type="file" name="test" />',
241        )
242
243
244class ForeignKeyRawIdWidgetTest(DjangoTestCase):
245    def test_render(self):
246        band = models.Band.objects.create(name='Linkin Park')
247        band.album_set.create(
248            name='Hybrid Theory', cover_art=r'albums\hybrid_theory.jpg'
249        )
250        rel = models.Album._meta.get_field('band').rel
251
252        w = ForeignKeyRawIdWidget(rel)
253        self.assertEqual(
254            conditional_escape(w.render('test', band.pk, attrs={})),
255            '<input type="text" name="test" value="%(bandpk)s" class="vForeignKeyRawIdAdminField" /><a href="../../../admin_widgets/band/?t=id" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" /></a>&nbsp;<strong>Linkin Park</strong>' % {"ADMIN_MEDIA_PREFIX": settings.ADMIN_MEDIA_PREFIX, "bandpk": band.pk},
256        )
257
258    def test_relations_to_non_primary_key(self):
259        # Check that ForeignKeyRawIdWidget works with fields which aren't
260        # related to the model's primary key.
261        apple = models.Inventory.objects.create(barcode=86, name='Apple')
262        models.Inventory.objects.create(barcode=22, name='Pear')
263        core = models.Inventory.objects.create(
264            barcode=87, name='Core', parent=apple
265        )
266        rel = models.Inventory._meta.get_field('parent').rel
267        w = ForeignKeyRawIdWidget(rel)
268        self.assertEqual(
269            w.render('test', core.parent_id, attrs={}),
270            '<input type="text" name="test" value="86" class="vForeignKeyRawIdAdminField" /><a href="../../../admin_widgets/inventory/?t=barcode" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" /></a>&nbsp;<strong>Apple</strong>' % {"ADMIN_MEDIA_PREFIX": settings.ADMIN_MEDIA_PREFIX},
271        )
272
273
274    def test_proper_manager_for_label_lookup(self):
275        # see #9258
276        rel = models.Inventory._meta.get_field('parent').rel
277        w = ForeignKeyRawIdWidget(rel)
278
279        hidden = models.Inventory.objects.create(
280            barcode=93, name='Hidden', hidden=True
281        )
282        child_of_hidden = models.Inventory.objects.create(
283            barcode=94, name='Child of hidden', parent=hidden
284        )
285        self.assertEqual(
286            w.render('test', child_of_hidden.parent_id, attrs={}),
287            '<input type="text" name="test" value="93" class="vForeignKeyRawIdAdminField" /><a href="../../../admin_widgets/inventory/?t=barcode" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" /></a>&nbsp;<strong>Hidden</strong>' % {"ADMIN_MEDIA_PREFIX": settings.ADMIN_MEDIA_PREFIX},
288        )
289
290
291class ManyToManyRawIdWidgetTest(DjangoTestCase):
292    def test_render(self):
293        band = models.Band.objects.create(name='Linkin Park')
294        band.album_set.create(
295            name='Hybrid Theory', cover_art=r'albums\hybrid_theory.jpg'
296        )
297
298        m1 = models.Member.objects.create(name='Chester')
299        m2 = models.Member.objects.create(name='Mike')
300        band.members.add(m1, m2)
301        rel = models.Band._meta.get_field('members').rel
302
303        w = ManyToManyRawIdWidget(rel)
304        self.assertEqual(
305            conditional_escape(w.render('test', [m1.pk, m2.pk], attrs={})),
306            '<input type="text" name="test" value="%(m1pk)s,%(m2pk)s" class="vManyToManyRawIdAdminField" /><a href="../../../admin_widgets/member/" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" /></a>' % {"ADMIN_MEDIA_PREFIX": settings.ADMIN_MEDIA_PREFIX, "m1pk": m1.pk, "m2pk": m2.pk},
307        )
308
309        self.assertEqual(
310            conditional_escape(w.render('test', [m1.pk])),
311            '<input type="text" name="test" value="%(m1pk)s" class="vManyToManyRawIdAdminField" /><a href="../../../admin_widgets/member/" class="related-lookup" id="lookup_id_test" onclick="return showRelatedObjectLookupPopup(this);"> <img src="%(ADMIN_MEDIA_PREFIX)simg/admin/selector-search.gif" width="16" height="16" alt="Lookup" /></a>' % {"ADMIN_MEDIA_PREFIX": settings.ADMIN_MEDIA_PREFIX, "m1pk": m1.pk},
312        )
313
314        self.assertEqual(w._has_changed(None, None), False)
315        self.assertEqual(w._has_changed([], None), False)
316        self.assertEqual(w._has_changed(None, [u'1']), True)
317        self.assertEqual(w._has_changed([1, 2], [u'1', u'2']), False)
318        self.assertEqual(w._has_changed([1, 2], [u'1']), True)
319        self.assertEqual(w._has_changed([1, 2], [u'1', u'3']), True)
320
321class RelatedFieldWidgetWrapperTests(DjangoTestCase):
322    def test_no_can_add_related(self):
323        rel = models.Inventory._meta.get_field('parent').rel
324        w = AdminRadioSelect()
325        # Used to fail with a name error.
326        w = RelatedFieldWidgetWrapper(w, rel, admin.site)
327        self.assertFalse(w.can_add_related)