summaryrefslogtreecommitdiff
path: root/tests/regressiontests
diff options
context:
space:
mode:
authorJacob Kaplan-Moss <jacob@jacobian.org>2009-01-16 15:32:31 +0000
committerJacob Kaplan-Moss <jacob@jacobian.org>2009-01-16 15:32:31 +0000
commitf212b24b6469b66424354bf970f3051df180b88d (patch)
tree379b8102f38ddde424cb0005cf2f468d409f691e /tests/regressiontests
parentd579e716fef9f06f04861815cf949630d8633271 (diff)
Cleaned up and refactored `ModelAdmin.formfield_for_dbfield`:
* The new method uses an admin configuration option (`formfield_overrides`); this makes custom admin widgets especially easy. * Refactored what was left of `formfield_for_dbfield` into a handful of smaller methods so that it's easier to hook in and return custom fields where needed. * These `formfield_for_*` methods now pass around `request` so that you can easily modify fields based on request (as in #3987). Fixes #8306, #3987, #9148. Thanks to James Bennet for the original patch; Alex Gaynor and Brian Rosner also contributed. git-svn-id: http://code.djangoproject.com/svn/django/trunk@9760 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests/regressiontests')
-rw-r--r--tests/regressiontests/admin_widgets/fixtures/admin-widgets-users.xml43
-rw-r--r--tests/regressiontests/admin_widgets/models.py25
-rw-r--r--tests/regressiontests/admin_widgets/tests.py112
-rw-r--r--tests/regressiontests/admin_widgets/urls.py7
-rw-r--r--tests/regressiontests/admin_widgets/widgetadmin.py22
5 files changed, 209 insertions, 0 deletions
diff --git a/tests/regressiontests/admin_widgets/fixtures/admin-widgets-users.xml b/tests/regressiontests/admin_widgets/fixtures/admin-widgets-users.xml
new file mode 100644
index 0000000000..b851562a1c
--- /dev/null
+++ b/tests/regressiontests/admin_widgets/fixtures/admin-widgets-users.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<django-objects version="1.0">
+ <object pk="100" model="auth.user">
+ <field type="CharField" name="username">super</field>
+ <field type="CharField" name="first_name">Super</field>
+ <field type="CharField" name="last_name">User</field>
+ <field type="CharField" name="email">super@example.com</field>
+ <field type="CharField" name="password">sha1$995a3$6011485ea3834267d719b4c801409b8b1ddd0158</field>
+ <field type="BooleanField" name="is_staff">True</field>
+ <field type="BooleanField" name="is_active">True</field>
+ <field type="BooleanField" name="is_superuser">True</field>
+ <field type="DateTimeField" name="last_login">2007-05-30 13:20:10</field>
+ <field type="DateTimeField" name="date_joined">2007-05-30 13:20:10</field>
+ <field to="auth.group" name="groups" rel="ManyToManyRel"></field>
+ <field to="auth.permission" name="user_permissions" rel="ManyToManyRel"></field>
+ </object>
+ <object pk="101" model="auth.user">
+ <field type="CharField" name="username">testser</field>
+ <field type="CharField" name="first_name">Add</field>
+ <field type="CharField" name="last_name">User</field>
+ <field type="CharField" name="email">auser@example.com</field>
+ <field type="CharField" name="password">sha1$995a3$6011485ea3834267d719b4c801409b8b1ddd0158</field>
+ <field type="BooleanField" name="is_staff">True</field>
+ <field type="BooleanField" name="is_active">True</field>
+ <field type="BooleanField" name="is_superuser">False</field>
+ <field type="DateTimeField" name="last_login">2007-05-30 13:20:10</field>
+ <field type="DateTimeField" name="date_joined">2007-05-30 13:20:10</field>
+ <field to="auth.group" name="groups" rel="ManyToManyRel"></field>
+ <field to="auth.permission" name="user_permissions" rel="ManyToManyRel"></field>
+ </object>
+
+ <object pk="1" model="admin_widgets.car">
+ <field to="auth.user" name="owner" rel="ManyToOneRel">100</field>
+ <field type="CharField" name="make">Volkswagon</field>
+ <field type="CharField" name="model">Passat</field>
+ </object>
+ <object pk="2" model="admin_widgets.car">
+ <field to="auth.user" name="owner" rel="ManyToOneRel">101</field>
+ <field type="CharField" name="make">BMW</field>
+ <field type="CharField" name="model">M3</field>
+ </object>
+
+</django-objects> \ No newline at end of file
diff --git a/tests/regressiontests/admin_widgets/models.py b/tests/regressiontests/admin_widgets/models.py
index ddfc6c2cb6..345d73b0ea 100644
--- a/tests/regressiontests/admin_widgets/models.py
+++ b/tests/regressiontests/admin_widgets/models.py
@@ -2,9 +2,12 @@
from django.conf import settings
from django.db import models
from django.core.files.storage import default_storage
+from django.contrib.auth.models import User
class Member(models.Model):
name = models.CharField(max_length=100)
+ birthdate = models.DateTimeField(blank=True, null=True)
+ gender = models.CharField(max_length=1, blank=True, choices=[('M','Male'), ('F', 'Female')])
def __unicode__(self):
return self.name
@@ -40,6 +43,28 @@ class Inventory(models.Model):
def __unicode__(self):
return self.name
+
+class Event(models.Model):
+ band = models.ForeignKey(Band)
+ date = models.DateField(blank=True, null=True)
+ start_time = models.TimeField(blank=True, null=True)
+ description = models.TextField(blank=True)
+ link = models.URLField(blank=True)
+ min_age = models.IntegerField(blank=True, null=True)
+
+class Car(models.Model):
+ owner = models.ForeignKey(User)
+ make = models.CharField(max_length=30)
+ model = models.CharField(max_length=30)
+
+ def __unicode__(self):
+ return u"%s %s" % (self.make, self.model)
+
+class CarTire(models.Model):
+ """
+ A single car tire. This to test that a user can only select their own cars.
+ """
+ car = models.ForeignKey(Car)
__test__ = {'WIDGETS_TESTS': """
>>> from datetime import datetime
diff --git a/tests/regressiontests/admin_widgets/tests.py b/tests/regressiontests/admin_widgets/tests.py
new file mode 100644
index 0000000000..2794b3fb80
--- /dev/null
+++ b/tests/regressiontests/admin_widgets/tests.py
@@ -0,0 +1,112 @@
+from django import forms
+from django.contrib import admin
+from django.contrib.admin import widgets
+from unittest import TestCase
+from django.test import TestCase as DjangoTestCase
+import models
+
+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.assert_(
+ 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, '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, 'date', forms.TextInput,
+ formfield_overrides={'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})
+
+
+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.assert_("BMW M3" not in response.content)
+ self.assert_("Volkswagon Passat" in response.content)
diff --git a/tests/regressiontests/admin_widgets/urls.py b/tests/regressiontests/admin_widgets/urls.py
new file mode 100644
index 0000000000..af73d5351d
--- /dev/null
+++ b/tests/regressiontests/admin_widgets/urls.py
@@ -0,0 +1,7 @@
+
+from django.conf.urls.defaults import *
+import widgetadmin
+
+urlpatterns = patterns('',
+ (r'^', include(widgetadmin.site.urls)),
+)
diff --git a/tests/regressiontests/admin_widgets/widgetadmin.py b/tests/regressiontests/admin_widgets/widgetadmin.py
new file mode 100644
index 0000000000..bc28dac86a
--- /dev/null
+++ b/tests/regressiontests/admin_widgets/widgetadmin.py
@@ -0,0 +1,22 @@
+"""
+
+"""
+from django.contrib import admin
+
+import models
+
+class WidgetAdmin(admin.AdminSite):
+ pass
+
+
+class CarTireAdmin(admin.ModelAdmin):
+ def formfield_for_foreignkey(self, db_field, request, **kwargs):
+ if db_field.name == "car":
+ kwargs["queryset"] = models.Car.objects.filter(owner=request.user)
+ return db_field.formfield(**kwargs)
+ return super(CarTireAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
+
+site = WidgetAdmin()
+
+site.register(models.Car)
+site.register(models.CarTire, CarTireAdmin)