# encoding: utf-8 from __future__ import with_statement from datetime import datetime from django import forms from django.conf import settings from django.contrib import admin from django.contrib.admin import widgets from django.core.files.storage import default_storage from django.core.files.uploadedfile import SimpleUploadedFile from django.db.models import DateField from django.test import TestCase as DjangoTestCase from django.utils import translation from django.utils.html import conditional_escape from django.utils.unittest import TestCase import models from widgetadmin import site as widget_admin_site admin_media_prefix = lambda: { 'ADMIN_MEDIA_PREFIX': "%sadmin/" % settings.STATIC_URL, } class AdminFormfieldForDBFieldTests(TestCase): """ Tests for correct behavior of ModelAdmin.formfield_for_dbfield """ def assertFormfield(self, model, fieldname, widgetclass, **admin_overrides): """ Helper to call formfield_for_dbfield for a given model and field name and verify that the returned formfield is appropriate. """ # Override any settings on the model admin class MyModelAdmin(admin.ModelAdmin): pass for k in admin_overrides: setattr(MyModelAdmin, k, admin_overrides[k]) # Construct the admin, and ask it for a formfield ma = MyModelAdmin(model, admin.site) ff = ma.formfield_for_dbfield(model._meta.get_field(fieldname), request=None) # "unwrap" the widget wrapper, if needed if isinstance(ff.widget, widgets.RelatedFieldWidgetWrapper): widget = ff.widget.widget else: widget = ff.widget # Check that we got a field of the right type self.assertTrue( isinstance(widget, widgetclass), "Wrong widget for %s.%s: expected %s, got %s" % \ (model.__class__.__name__, fieldname, widgetclass, type(widget)) ) # Return the formfield so that other tests can continue return ff def testDateField(self): self.assertFormfield(models.Event, 'start_date', widgets.AdminDateWidget) def testDateTimeField(self): self.assertFormfield(models.Member, 'birthdate', widgets.AdminSplitDateTime) def testTimeField(self): self.assertFormfield(models.Event, 'start_time', widgets.AdminTimeWidget) def testTextField(self): self.assertFormfield(models.Event, 'description', widgets.AdminTextareaWidget) def testURLField(self): self.assertFormfield(models.Event, 'link', widgets.AdminURLFieldWidget) def testIntegerField(self): self.assertFormfield(models.Event, 'min_age', widgets.AdminIntegerFieldWidget) def testCharField(self): self.assertFormfield(models.Member, 'name', widgets.AdminTextInputWidget) def testFileField(self): self.assertFormfield(models.Album, 'cover_art', widgets.AdminFileWidget) def testForeignKey(self): self.assertFormfield(models.Event, 'band', forms.Select) def testRawIDForeignKey(self): self.assertFormfield(models.Event, 'band', widgets.ForeignKeyRawIdWidget, raw_id_fields=['band']) def testRadioFieldsForeignKey(self): ff = self.assertFormfield(models.Event, 'band', widgets.AdminRadioSelect, radio_fields={'band':admin.VERTICAL}) self.assertEqual(ff.empty_label, None) def testManyToMany(self): self.assertFormfield(models.Band, 'members', forms.SelectMultiple) def testRawIDManyTOMany(self): self.assertFormfield(models.Band, 'members', widgets.ManyToManyRawIdWidget, raw_id_fields=['members']) def testFilteredManyToMany(self): self.assertFormfield(models.Band, 'members', widgets.FilteredSelectMultiple, filter_vertical=['members']) def testFormfieldOverrides(self): self.assertFormfield(models.Event, 'start_date', forms.TextInput, formfield_overrides={DateField: {'widget': forms.TextInput}}) def testFieldWithChoices(self): self.assertFormfield(models.Member, 'gender', forms.Select) def testChoicesWithRadioFields(self): self.assertFormfield(models.Member, 'gender', widgets.AdminRadioSelect, radio_fields={'gender':admin.VERTICAL}) def testInheritance(self): self.assertFormfield(models.Album, 'backside_art', widgets.AdminFileWidget) class AdminFormfieldForDBFieldWithRequestTests(DjangoTestCase): fixtures = ["admin-widgets-users.xml"] def testFilterChoicesByRequestUser(self): """ Ensure the user can only see their own cars in the foreign key dropdown. """ self.client.login(username="super", password="secret") response = self.client.get("/widget_admin/admin_widgets/cartire/add/") self.assertTrue("BMW M3" not in response.content) self.assertTrue("Volkswagon Passat" in response.content) class AdminForeignKeyWidgetChangeList(DjangoTestCase): fixtures = ["admin-widgets-users.xml"] admin_root = '/widget_admin' def setUp(self): self.client.login(username="super", password="secret") def tearDown(self): self.client.logout() def test_changelist_foreignkey(self): response = self.client.get('%s/admin_widgets/car/' % self.admin_root) self.assertTrue('%s/auth/user/add/' % self.admin_root in response.content) class AdminForeignKeyRawIdWidget(DjangoTestCase): fixtures = ["admin-widgets-users.xml"] admin_root = '/widget_admin' def setUp(self): self.client.login(username="super", password="secret") def tearDown(self): self.client.logout() def test_nonexistent_target_id(self): band = models.Band.objects.create(name='Bogey Blues') pk = band.pk band.delete() post_data = { "band": u'%s' % pk, } # Try posting with a non-existent pk in a raw id field: this # should result in an error message, not a server exception. response = self.client.post('%s/admin_widgets/event/add/' % self.admin_root, post_data) self.assertContains(response, 'Select a valid choice. That choice is not one of the available choices.') def test_invalid_target_id(self): for test_str in ('Iñtërnâtiônàlizætiøn', "1234'", -1234): # This should result in an error message, not a server exception. response = self.client.post('%s/admin_widgets/event/add/' % self.admin_root, {"band": test_str}) self.assertContains(response, 'Select a valid choice. That choice is not one of the available choices.') def test_url_params_from_lookup_dict_any_iterable(self): lookup1 = widgets.url_params_from_lookup_dict({'color__in': ('red', 'blue')}) lookup2 = widgets.url_params_from_lookup_dict({'color__in': ['red', 'blue']}) self.assertEqual(lookup1, {'color__in': 'red,blue'}) self.assertEqual(lookup1, lookup2) class FilteredSelectMultipleWidgetTest(DjangoTestCase): def test_render(self): w = widgets.FilteredSelectMultiple('test', False) self.assertEqual( conditional_escape(w.render('test', 'test')), '\n' % admin_media_prefix() ) def test_stacked_render(self): w = widgets.FilteredSelectMultiple('test', True) self.assertEqual( conditional_escape(w.render('test', 'test')), '\n' % admin_media_prefix() ) class AdminSplitDateTimeWidgetTest(DjangoTestCase): def test_render(self): w = widgets.AdminSplitDateTime() self.assertEqual( conditional_escape(w.render('test', datetime(2007, 12, 1, 9, 30))), '
Date: 
Time: 
Datum: 
Zeit: 
Currently: albums\hybrid_theory.jpg  
Change: 
simg/selector-search.gif) Linkin Park' % dict(admin_media_prefix(), bandpk=band.pk)
        )
    def test_relations_to_non_primary_key(self):
        # Check that ForeignKeyRawIdWidget works with fields which aren't
        # related to the model's primary key.
        apple = models.Inventory.objects.create(barcode=86, name='Apple')
        models.Inventory.objects.create(barcode=22, name='Pear')
        core = models.Inventory.objects.create(
            barcode=87, name='Core', parent=apple
        )
        rel = models.Inventory._meta.get_field('parent').rel
        w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site)
        self.assertEqual(
            w.render('test', core.parent_id, attrs={}),
            '
 Linkin Park' % dict(admin_media_prefix(), bandpk=band.pk)
        )
    def test_relations_to_non_primary_key(self):
        # Check that ForeignKeyRawIdWidget works with fields which aren't
        # related to the model's primary key.
        apple = models.Inventory.objects.create(barcode=86, name='Apple')
        models.Inventory.objects.create(barcode=22, name='Pear')
        core = models.Inventory.objects.create(
            barcode=87, name='Core', parent=apple
        )
        rel = models.Inventory._meta.get_field('parent').rel
        w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site)
        self.assertEqual(
            w.render('test', core.parent_id, attrs={}),
            ' simg/selector-search.gif) Apple' % admin_media_prefix()
        )
    def test_fk_related_model_not_in_admin(self):
        # FK to a model not registered with admin site. Raw ID widget should
        # have no magnifying glass link. See #16542
        big_honeycomb = models.Honeycomb.objects.create(location='Old tree')
        big_honeycomb.bee_set.create()
        rel = models.Bee._meta.get_field('honeycomb').rel
        w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site)
        self.assertEqual(
            conditional_escape(w.render('honeycomb_widget', big_honeycomb.pk, attrs={})),
            ' Honeycomb object' % {'hcombpk': big_honeycomb.pk}
        )
    def test_fk_to_self_model_not_in_admin(self):
        # FK to self, not registered with admin site. Raw ID widget should have
        # no magnifying glass link. See #16542
        subject1 = models.Individual.objects.create(name='Subject #1')
        models.Individual.objects.create(name='Child', parent=subject1)
        rel = models.Individual._meta.get_field('parent').rel
        w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site)
        self.assertEqual(
            conditional_escape(w.render('individual_widget', subject1.pk, attrs={})),
            ' Individual object' % {'subj1pk': subject1.pk}
        )
    def test_proper_manager_for_label_lookup(self):
        # see #9258
        rel = models.Inventory._meta.get_field('parent').rel
        w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site)
        hidden = models.Inventory.objects.create(
            barcode=93, name='Hidden', hidden=True
        )
        child_of_hidden = models.Inventory.objects.create(
            barcode=94, name='Child of hidden', parent=hidden
        )
        self.assertEqual(
            w.render('test', child_of_hidden.parent_id, attrs={}),
            '
 Apple' % admin_media_prefix()
        )
    def test_fk_related_model_not_in_admin(self):
        # FK to a model not registered with admin site. Raw ID widget should
        # have no magnifying glass link. See #16542
        big_honeycomb = models.Honeycomb.objects.create(location='Old tree')
        big_honeycomb.bee_set.create()
        rel = models.Bee._meta.get_field('honeycomb').rel
        w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site)
        self.assertEqual(
            conditional_escape(w.render('honeycomb_widget', big_honeycomb.pk, attrs={})),
            ' Honeycomb object' % {'hcombpk': big_honeycomb.pk}
        )
    def test_fk_to_self_model_not_in_admin(self):
        # FK to self, not registered with admin site. Raw ID widget should have
        # no magnifying glass link. See #16542
        subject1 = models.Individual.objects.create(name='Subject #1')
        models.Individual.objects.create(name='Child', parent=subject1)
        rel = models.Individual._meta.get_field('parent').rel
        w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site)
        self.assertEqual(
            conditional_escape(w.render('individual_widget', subject1.pk, attrs={})),
            ' Individual object' % {'subj1pk': subject1.pk}
        )
    def test_proper_manager_for_label_lookup(self):
        # see #9258
        rel = models.Inventory._meta.get_field('parent').rel
        w = widgets.ForeignKeyRawIdWidget(rel, widget_admin_site)
        hidden = models.Inventory.objects.create(
            barcode=93, name='Hidden', hidden=True
        )
        child_of_hidden = models.Inventory.objects.create(
            barcode=94, name='Child of hidden', parent=hidden
        )
        self.assertEqual(
            w.render('test', child_of_hidden.parent_id, attrs={}),
            ' simg/selector-search.gif) Hidden' % admin_media_prefix()
        )
class ManyToManyRawIdWidgetTest(DjangoTestCase):
    def test_render(self):
        band = models.Band.objects.create(name='Linkin Park')
        m1 = models.Member.objects.create(name='Chester')
        m2 = models.Member.objects.create(name='Mike')
        band.members.add(m1, m2)
        rel = models.Band._meta.get_field('members').rel
        w = widgets.ManyToManyRawIdWidget(rel, widget_admin_site)
        self.assertEqual(
            conditional_escape(w.render('test', [m1.pk, m2.pk], attrs={})),
            '
 Hidden' % admin_media_prefix()
        )
class ManyToManyRawIdWidgetTest(DjangoTestCase):
    def test_render(self):
        band = models.Band.objects.create(name='Linkin Park')
        m1 = models.Member.objects.create(name='Chester')
        m2 = models.Member.objects.create(name='Mike')
        band.members.add(m1, m2)
        rel = models.Band._meta.get_field('members').rel
        w = widgets.ManyToManyRawIdWidget(rel, widget_admin_site)
        self.assertEqual(
            conditional_escape(w.render('test', [m1.pk, m2.pk], attrs={})),
            '  ' % dict(admin_media_prefix(), m1pk=m1.pk, m2pk=m2.pk)
        )
        self.assertEqual(
            conditional_escape(w.render('test', [m1.pk])),
            '
' % dict(admin_media_prefix(), m1pk=m1.pk, m2pk=m2.pk)
        )
        self.assertEqual(
            conditional_escape(w.render('test', [m1.pk])),
            ' simg/selector-search.gif) ' % dict(admin_media_prefix(), m1pk=m1.pk)
        )
        self.assertEqual(w._has_changed(None, None), False)
        self.assertEqual(w._has_changed([], None), False)
        self.assertEqual(w._has_changed(None, [u'1']), True)
        self.assertEqual(w._has_changed([1, 2], [u'1', u'2']), False)
        self.assertEqual(w._has_changed([1, 2], [u'1']), True)
        self.assertEqual(w._has_changed([1, 2], [u'1', u'3']), True)
    def test_m2m_related_model_not_in_admin(self):
        # M2M relationship with model not registered with admin site. Raw ID
        # widget should have no magnifying glass link. See #16542
        consultor1 = models.Advisor.objects.create(name='Rockstar Techie')
        c1 = models.Company.objects.create(name='Doodle')
        c2 = models.Company.objects.create(name='Pear')
        consultor1.companies.add(c1, c2)
        rel = models.Advisor._meta.get_field('companies').rel
        w = widgets.ManyToManyRawIdWidget(rel, widget_admin_site)
        self.assertEqual(
            conditional_escape(w.render('company_widget1', [c1.pk, c2.pk], attrs={})),
            '' % {'c1pk': c1.pk, 'c2pk': c2.pk}
        )
        self.assertEqual(
            conditional_escape(w.render('company_widget2', [c1.pk])),
            '' % {'c1pk': c1.pk}
        )
class RelatedFieldWidgetWrapperTests(DjangoTestCase):
    def test_no_can_add_related(self):
        rel = models.Individual._meta.get_field('parent').rel
        w = widgets.AdminRadioSelect()
        # Used to fail with a name error.
        w = widgets.RelatedFieldWidgetWrapper(w, rel, widget_admin_site)
        self.assertFalse(w.can_add_related)
' % dict(admin_media_prefix(), m1pk=m1.pk)
        )
        self.assertEqual(w._has_changed(None, None), False)
        self.assertEqual(w._has_changed([], None), False)
        self.assertEqual(w._has_changed(None, [u'1']), True)
        self.assertEqual(w._has_changed([1, 2], [u'1', u'2']), False)
        self.assertEqual(w._has_changed([1, 2], [u'1']), True)
        self.assertEqual(w._has_changed([1, 2], [u'1', u'3']), True)
    def test_m2m_related_model_not_in_admin(self):
        # M2M relationship with model not registered with admin site. Raw ID
        # widget should have no magnifying glass link. See #16542
        consultor1 = models.Advisor.objects.create(name='Rockstar Techie')
        c1 = models.Company.objects.create(name='Doodle')
        c2 = models.Company.objects.create(name='Pear')
        consultor1.companies.add(c1, c2)
        rel = models.Advisor._meta.get_field('companies').rel
        w = widgets.ManyToManyRawIdWidget(rel, widget_admin_site)
        self.assertEqual(
            conditional_escape(w.render('company_widget1', [c1.pk, c2.pk], attrs={})),
            '' % {'c1pk': c1.pk, 'c2pk': c2.pk}
        )
        self.assertEqual(
            conditional_escape(w.render('company_widget2', [c1.pk])),
            '' % {'c1pk': c1.pk}
        )
class RelatedFieldWidgetWrapperTests(DjangoTestCase):
    def test_no_can_add_related(self):
        rel = models.Individual._meta.get_field('parent').rel
        w = widgets.AdminRadioSelect()
        # Used to fail with a name error.
        w = widgets.RelatedFieldWidgetWrapper(w, rel, widget_admin_site)
        self.assertFalse(w.can_add_related)