diff options
| author | Brian Rosner <brosner@gmail.com> | 2008-11-13 19:05:49 +0000 |
|---|---|---|
| committer | Brian Rosner <brosner@gmail.com> | 2008-11-13 19:05:49 +0000 |
| commit | f219136e11f56a5765b58af476c93e806b2f3ce0 (patch) | |
| tree | f6c4eebeee81d8f5a68d32bf4e8c038da13626d5 | |
| parent | c8dcbb038af7fc901c750853a8a2e06bcc027e87 (diff) | |
[1.0.X] Fixed #9498 -- Handle a formset correctly when the foreign key is not available (for now).
This case pops up with generic foreign key inlines after [9297]. Added tests
to handle future regressions with generic foreign key inlines in the admin.
Thanks markus and danielr for patches.
Backport of [9412] from trunk.
git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.0.X@9413 bcc190cf-cafb-0310-a4f2-bffc1f526a37
| -rw-r--r-- | django/contrib/admin/helpers.py | 12 | ||||
| -rw-r--r-- | tests/regressiontests/generic_inline_admin/__init__.py | 0 | ||||
| -rw-r--r-- | tests/regressiontests/generic_inline_admin/fixtures/model-data.xml | 11 | ||||
| -rw-r--r-- | tests/regressiontests/generic_inline_admin/fixtures/users.xml | 17 | ||||
| -rw-r--r-- | tests/regressiontests/generic_inline_admin/models.py | 30 | ||||
| -rw-r--r-- | tests/regressiontests/generic_inline_admin/tests.py | 66 | ||||
| -rw-r--r-- | tests/regressiontests/generic_inline_admin/urls.py | 6 | ||||
| -rw-r--r-- | tests/urls.py | 1 |
8 files changed, 140 insertions, 3 deletions
diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py index e969a41390..aaa2e304ce 100644 --- a/django/contrib/admin/helpers.py +++ b/django/contrib/admin/helpers.py @@ -108,8 +108,9 @@ class InlineAdminFormSet(object): yield InlineAdminForm(self.formset, form, self.fieldsets, self.opts.prepopulated_fields, None) def fields(self): + fk = getattr(self.formset, "fk", None) for field_name in flatten_fieldsets(self.fieldsets): - if self.formset.fk.name == field_name: + if fk and fk.name == field_name: continue yield self.formset.form.base_fields[field_name] @@ -150,7 +151,11 @@ class InlineAdminForm(AdminForm): return AdminField(self.form, self.formset._pk_field.name, False) def fk_field(self): - return AdminField(self.form, self.formset.fk.name, False) + fk = getattr(self.formset, "fk", None) + if fk: + return AdminField(self.form, fk.name, False) + else: + return "" def deletion_field(self): from django.forms.formsets import DELETION_FIELD_NAME @@ -166,8 +171,9 @@ class InlineFieldset(Fieldset): super(InlineFieldset, self).__init__(*args, **kwargs) def __iter__(self): + fk = getattr(self.formset, "fk", None) for field in self.fields: - if self.formset.fk.name == field: + if fk and fk.name == field: continue yield Fieldline(self.form, field) diff --git a/tests/regressiontests/generic_inline_admin/__init__.py b/tests/regressiontests/generic_inline_admin/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/regressiontests/generic_inline_admin/__init__.py diff --git a/tests/regressiontests/generic_inline_admin/fixtures/model-data.xml b/tests/regressiontests/generic_inline_admin/fixtures/model-data.xml new file mode 100644 index 0000000000..a629208d2d --- /dev/null +++ b/tests/regressiontests/generic_inline_admin/fixtures/model-data.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<django-objects version="1.0"> + <object pk="1" model="generic_inline_admin.Episode"> + <field type="CharField" name="name">This Week in Django</field> + </object> + <object pk="1" model="generic_inline_admin.Media"> + <field type="ForeignKey" name="content_type">13</field> + <field type="PositiveIntegerField" name="object_id">1</field> + <field type="URLField" name="url">http://example.com/podcast.mp3</field> + </object> +</django-objects>
\ No newline at end of file diff --git a/tests/regressiontests/generic_inline_admin/fixtures/users.xml b/tests/regressiontests/generic_inline_admin/fixtures/users.xml new file mode 100644 index 0000000000..6cf441f01e --- /dev/null +++ b/tests/regressiontests/generic_inline_admin/fixtures/users.xml @@ -0,0 +1,17 @@ +<?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> +</django-objects>
\ No newline at end of file diff --git a/tests/regressiontests/generic_inline_admin/models.py b/tests/regressiontests/generic_inline_admin/models.py new file mode 100644 index 0000000000..6e9fbebabb --- /dev/null +++ b/tests/regressiontests/generic_inline_admin/models.py @@ -0,0 +1,30 @@ +from django.db import models +from django.contrib import admin +from django.contrib.contenttypes import generic +from django.contrib.contenttypes.models import ContentType + +class Episode(models.Model): + name = models.CharField(max_length=100) + +class Media(models.Model): + """ + Media that can associated to any object. + """ + content_type = models.ForeignKey(ContentType) + object_id = models.PositiveIntegerField() + content_object = generic.GenericForeignKey() + url = models.URLField(verify_exists=False) + + def __unicode__(self): + return self.url + +class MediaInline(generic.GenericTabularInline): + model = Media + extra = 1 + +class EpisodeAdmin(admin.ModelAdmin): + inlines = [ + MediaInline, + ] + +admin.site.register(Episode, EpisodeAdmin) diff --git a/tests/regressiontests/generic_inline_admin/tests.py b/tests/regressiontests/generic_inline_admin/tests.py new file mode 100644 index 0000000000..f2953fee54 --- /dev/null +++ b/tests/regressiontests/generic_inline_admin/tests.py @@ -0,0 +1,66 @@ +# coding: utf-8 + +from django.test import TestCase +from django.conf import settings + +# local test models +from models import Episode, Media + +class GenericAdminViewTest(TestCase): + fixtures = ['users.xml', 'model-data.xml'] + + def setUp(self): + # set TEMPLATE_DEBUG to True to ensure {% include %} will raise + # exceptions since that is how inlines are rendered and #9498 will + # bubble up if it is an issue. + self.original_template_debug = settings.TEMPLATE_DEBUG + settings.TEMPLATE_DEBUG = True + self.client.login(username='super', password='secret') + + def tearDown(self): + self.client.logout() + settings.TEMPLATE_DEBUG = self.original_template_debug + + def testBasicAddGet(self): + """ + A smoke test to ensure GET on the add_view works. + """ + response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/episode/add/') + self.failUnlessEqual(response.status_code, 200) + + def testBasicEditGet(self): + """ + A smoke test to ensure GET on the change_view works. + """ + response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/episode/1/') + self.failUnlessEqual(response.status_code, 200) + + def testBasicAddPost(self): + """ + A smoke test to ensure POST on add_view works. + """ + post_data = { + "name": u"This Week in Django", + # inline data + "generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"1", + "generic_inline_admin-media-content_type-object_id-INITIAL_FORMS": u"0", + } + response = self.client.post('/generic_inline_admin/admin/generic_inline_admin/episode/add/', post_data) + self.failUnlessEqual(response.status_code, 302) # redirect somewhere + + def testBasicEditPost(self): + """ + A smoke test to ensure POST on edit_view works. + """ + post_data = { + "name": u"This Week in Django", + # inline data + "generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"2", + "generic_inline_admin-media-content_type-object_id-INITIAL_FORMS": u"1", + "generic_inline_admin-media-content_type-object_id-0-id": u"1", + "generic_inline_admin-media-content_type-object_id-0-url": u"http://example.com/podcast.mp3", + "generic_inline_admin-media-content_type-object_id-1-id": u"", + "generic_inline_admin-media-content_type-object_id-1-url": u"", + } + response = self.client.post('/generic_inline_admin/admin/generic_inline_admin/episode/1/', post_data) + self.failUnlessEqual(response.status_code, 302) # redirect somewhere diff --git a/tests/regressiontests/generic_inline_admin/urls.py b/tests/regressiontests/generic_inline_admin/urls.py new file mode 100644 index 0000000000..04d68cd26c --- /dev/null +++ b/tests/regressiontests/generic_inline_admin/urls.py @@ -0,0 +1,6 @@ +from django.conf.urls.defaults import * +from django.contrib import admin + +urlpatterns = patterns('', + (r'^admin/(.*)', admin.site.root), +) diff --git a/tests/urls.py b/tests/urls.py index a8dc583aa1..b6c9d6e030 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -23,6 +23,7 @@ urlpatterns = patterns('', # admin view tests (r'^test_admin/', include('regressiontests.admin_views.urls')), + (r'^generic_inline_admin/', include('regressiontests.generic_inline_admin.urls')), (r'^utils/', include('regressiontests.utils.urls')), |
