Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #12475 -- Fixed an edge case with hidden fields in ModelAdmin c…

…hangelists when used in conjunction with list_display_links or list_editable. Thanks, Simon Meers, Julien Phalip, Karen and master.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15722 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit b921f1bac090cecd87e0b99b4c7c2d7581bcf2da 1 parent c0fb9bd
Jannis Leidel authored March 03, 2011
2  django/contrib/admin/templates/admin/change_list_results.html
... ...
@@ -1,5 +1,5 @@
1 1
 {% if result_hidden_fields %}
2  
-<div class="hiddenfields"> {# DIV for HTML validation #}
  2
+<div class="hiddenfields">{# DIV for HTML validation #}
3 3
 {% for item in result_hidden_fields %}{{ item }}{% endfor %}
4 4
 </div>
5 5
 {% endif %}
4  django/contrib/admin/templatetags/admin_list.py
@@ -188,7 +188,9 @@ def items_for_result(cl, result, form):
188 188
             # By default the fields come from ModelAdmin.list_editable, but if we pull
189 189
             # the fields out of the form instead of list_editable custom admins
190 190
             # can provide fields on a per request basis
191  
-            if form and field_name in form.fields:
  191
+            if (form and field_name in form.fields and not (
  192
+                    field_name == cl.model._meta.pk.name and
  193
+                        form[cl.model._meta.pk.name].is_hidden)):
192 194
                 bf = form[field_name]
193 195
                 result_repr = mark_safe(force_unicode(bf.errors) + force_unicode(bf))
194 196
             else:
24  tests/regressiontests/admin_views/models.py
@@ -735,6 +735,28 @@ def queryset(self, request):
735 735
         #return super(CoverLetterAdmin, self).queryset(request).only('author')
736 736
         return super(CoverLetterAdmin, self).queryset(request).defer('date')
737 737
 
  738
+class Story(models.Model):
  739
+    title = models.CharField(max_length=100)
  740
+    content = models.TextField()
  741
+
  742
+class StoryForm(forms.ModelForm):
  743
+    class Meta:
  744
+        widgets = {'title': forms.HiddenInput}
  745
+
  746
+class StoryAdmin(admin.ModelAdmin):
  747
+    list_display = ('id', 'title', 'content')
  748
+    list_display_links = ('title',) # 'id' not in list_display_links
  749
+    list_editable = ('content', )
  750
+    form = StoryForm
  751
+
  752
+class OtherStory(models.Model):
  753
+    title = models.CharField(max_length=100)
  754
+    content = models.TextField()
  755
+
  756
+class OtherStoryAdmin(admin.ModelAdmin):
  757
+    list_display = ('id', 'title', 'content')
  758
+    list_display_links = ('title', 'id') # 'id' in list_display_links
  759
+    list_editable = ('content', )
738 760
 
739 761
 admin.site.register(Article, ArticleAdmin)
740 762
 admin.site.register(CustomArticle, CustomArticleAdmin)
@@ -776,6 +798,8 @@ def queryset(self, request):
776 798
 admin.site.register(RowLevelChangePermissionModel, RowLevelChangePermissionModelAdmin)
777 799
 admin.site.register(Paper, PaperAdmin)
778 800
 admin.site.register(CoverLetter, CoverLetterAdmin)
  801
+admin.site.register(Story, StoryAdmin)
  802
+admin.site.register(OtherStory, OtherStoryAdmin)
779 803
 
780 804
 # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
781 805
 # That way we cover all four cases:
32  tests/regressiontests/admin_views/tests.py
@@ -36,7 +36,7 @@
36 36
     Language, Collector, Widget, Grommet, DooHickey, FancyDoodad, Whatsit,
37 37
     Category, Post, Plot, FunkyTag, Chapter, Book, Promo, WorkHour, Employee,
38 38
     Question, Answer, Inquisition, Actor, FoodDelivery,
39  
-    RowLevelChangePermissionModel, Paper, CoverLetter)
  39
+    RowLevelChangePermissionModel, Paper, CoverLetter, Story, OtherStory)
40 40
 
41 41
 
42 42
 class AdminViewBasicTest(TestCase):
@@ -1678,6 +1678,36 @@ def test_list_editable_popup(self):
1678 1678
         response = self.client.get('/test_admin/admin/admin_views/person/?%s' % IS_POPUP_VAR)
1679 1679
         self.assertEqual(response.context['cl'].list_editable, ())
1680 1680
 
  1681
+    def test_pk_hidden_fields(self):
  1682
+        """ Ensure that hidden pk fields aren't displayed in the table body and
  1683
+            that their corresponding human-readable value is displayed instead.
  1684
+            Note that the hidden pk fields are in fact be displayed but
  1685
+            separately (not in the table), and only once.
  1686
+            Refs #12475.
  1687
+        """
  1688
+        Story.objects.create(title='The adventures of Guido', content='Once upon a time in Djangoland...')
  1689
+        Story.objects.create(title='Crouching Tiger, Hidden Python', content='The Python was sneaking into...')
  1690
+        response = self.client.get('/test_admin/admin/admin_views/story/')
  1691
+        self.assertContains(response, 'id="id_form-0-id"', 1) # Only one hidden field, in a separate place than the table.
  1692
+        self.assertContains(response, 'id="id_form-1-id"', 1)
  1693
+        self.assertContains(response, '<div class="hiddenfields">\n<input type="hidden" name="form-0-id" value="2" id="id_form-0-id" /><input type="hidden" name="form-1-id" value="1" id="id_form-1-id" />\n</div>')
  1694
+        self.assertContains(response, '<td>1</td>', 1)
  1695
+        self.assertContains(response, '<td>2</td>', 1)
  1696
+
  1697
+    def test_pk_hidden_fields_with_list_display_links(self):
  1698
+        """ Similarly as test_pk_hidden_fields, but when the hidden pk fields are
  1699
+            referenced in list_display_links.
  1700
+            Refs #12475.
  1701
+        """
  1702
+        OtherStory.objects.create(title='The adventures of Guido', content='Once upon a time in Djangoland...')
  1703
+        OtherStory.objects.create(title='Crouching Tiger, Hidden Python', content='The Python was sneaking into...')
  1704
+        response = self.client.get('/test_admin/admin/admin_views/otherstory/')
  1705
+        self.assertContains(response, 'id="id_form-0-id"', 1) # Only one hidden field, in a separate place than the table.
  1706
+        self.assertContains(response, 'id="id_form-1-id"', 1)
  1707
+        self.assertContains(response, '<div class="hiddenfields">\n<input type="hidden" name="form-0-id" value="2" id="id_form-0-id" /><input type="hidden" name="form-1-id" value="1" id="id_form-1-id" />\n</div>')
  1708
+        self.assertContains(response, '<th><a href="1/">1</a></th>', 1)
  1709
+        self.assertContains(response, '<th><a href="2/">2</a></th>', 1)
  1710
+
1681 1711
 
1682 1712
 class AdminSearchTest(TestCase):
1683 1713
     fixtures = ['admin-views-users', 'multiple-child-classes',

0 notes on commit b921f1b

Please sign in to comment.
Something went wrong with that request. Please try again.