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