Ticket #10271: admin_formset_inheritance.3.diff
File admin_formset_inheritance.3.diff, 15.6 KB (added by , 16 years ago) |
---|
-
django/contrib/admin/options.py
522 522 else: 523 523 form_validated = False 524 524 new_object = self.model() 525 for FormSet in self.get_formsets(request):525 for idx, FormSet in enumerate(self.get_formsets(request)): 526 526 formset = FormSet(data=request.POST, files=request.FILES, 527 527 instance=new_object, 528 save_as_new=request.POST.has_key("_saveasnew")) 528 save_as_new=request.POST.has_key("_saveasnew"), 529 prefix="form-%s" % idx) 529 530 formsets.append(formset) 530 531 if all_valid(formsets) and form_validated: 531 532 self.save_model(request, new_object, form, change=False) … … 547 548 if isinstance(f, models.ManyToManyField): 548 549 initial[k] = initial[k].split(",") 549 550 form = ModelForm(initial=initial) 550 for FormSet in self.get_formsets(request):551 formset = FormSet(instance=self.model() )551 for idx, FormSet in enumerate(self.get_formsets(request)): 552 formset = FormSet(instance=self.model(), prefix="form-%s" % idx) 552 553 formsets.append(formset) 553 554 554 555 adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)), self.prepopulated_fields) … … 608 609 else: 609 610 form_validated = False 610 611 new_object = obj 611 for FormSet in self.get_formsets(request, new_object):612 for idx, FormSet in enumerate(self.get_formsets(request, new_object)): 612 613 formset = FormSet(request.POST, request.FILES, 613 instance=new_object )614 instance=new_object, prefix="form-%s" % idx) 614 615 formsets.append(formset) 615 616 616 617 if all_valid(formsets) and form_validated: … … 625 626 626 627 else: 627 628 form = ModelForm(instance=obj) 628 for FormSet in self.get_formsets(request, obj):629 formset = FormSet(instance=obj )629 for idx, FormSet in enumerate(self.get_formsets(request, obj)): 630 formset = FormSet(instance=obj, prefix="form-%s" % idx) 630 631 formsets.append(formset) 631 632 632 633 adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj), self.prepopulated_fields) -
django/contrib/contenttypes/generic.py
291 291 ct_field_name = "content_type" 292 292 ct_fk_field_name = "object_id" 293 293 294 def __init__(self, data=None, files=None, instance=None, save_as_new=None): 294 def __init__(self, data=None, files=None, instance=None, prefix=None, 295 save_as_new=None): 295 296 opts = self.model._meta 296 297 self.instance = instance 297 298 self.rel_name = '-'.join(( … … 300 301 )) 301 302 super(BaseGenericInlineFormSet, self).__init__( 302 303 queryset=self.get_queryset(), data=data, files=files, 303 prefix= self.rel_name304 prefix=prefix or self.rel_name 304 305 ) 305 306 306 307 def get_queryset(self): -
tests/regressiontests/admin_views/tests.py
9 9 from django.utils.html import escape 10 10 11 11 # local test models 12 from models import Article, CustomArticle, Section, ModelWithStringPrimaryKey 12 from models import Article, CustomArticle, Section, ModelWithStringPrimaryKey, Persona, FooAccount, BarAccount 13 13 14 14 class AdminViewBasicTest(TestCase): 15 15 fixtures = ['admin-views-users.xml', 'admin-views-colors.xml'] … … 63 63 post_data = { 64 64 "name": u"Another Section", 65 65 # inline data 66 " article_set-TOTAL_FORMS": u"3",67 " article_set-INITIAL_FORMS": u"0",66 "form-0-TOTAL_FORMS": u"3", 67 "form-0-INITIAL_FORMS": u"0", 68 68 } 69 69 response = self.client.post('/test_admin/%s/admin_views/section/add/' % self.urlbit, post_data) 70 70 self.failUnlessEqual(response.status_code, 302) # redirect somewhere … … 76 76 post_data = { 77 77 "name": u"Test section", 78 78 # inline data 79 " article_set-TOTAL_FORMS": u"6",80 " article_set-INITIAL_FORMS": u"3",81 " article_set-0-id": u"1",79 "form-0-TOTAL_FORMS": u"6", 80 "form-0-INITIAL_FORMS": u"3", 81 "form-0-0-id": u"1", 82 82 # there is no title in database, give one here or formset 83 83 # will fail. 84 " article_set-0-title": u"Norske bostaver æøå skaper problemer",85 " article_set-0-content": u"<p>Middle content</p>",86 " article_set-0-date_0": u"2008-03-18",87 " article_set-0-date_1": u"11:54:58",88 " article_set-1-id": u"2",89 " article_set-1-title": u"Need a title.",90 " article_set-1-content": u"<p>Oldest content</p>",91 " article_set-1-date_0": u"2000-03-18",92 " article_set-1-date_1": u"11:54:58",93 " article_set-2-id": u"3",94 " article_set-2-title": u"Need a title.",95 " article_set-2-content": u"<p>Newest content</p>",96 " article_set-2-date_0": u"2009-03-18",97 " article_set-2-date_1": u"11:54:58",98 " article_set-3-id": u"",99 " article_set-3-title": u"",100 " article_set-3-content": u"",101 " article_set-3-date_0": u"",102 " article_set-3-date_1": u"",103 " article_set-4-id": u"",104 " article_set-4-title": u"",105 " article_set-4-content": u"",106 " article_set-4-date_0": u"",107 " article_set-4-date_1": u"",108 " article_set-5-id": u"",109 " article_set-5-title": u"",110 " article_set-5-content": u"",111 " article_set-5-date_0": u"",112 " article_set-5-date_1": u"",84 "form-0-0-title": u"Norske bostaver æøå skaper problemer", 85 "form-0-0-content": u"<p>Middle content</p>", 86 "form-0-0-date_0": u"2008-03-18", 87 "form-0-0-date_1": u"11:54:58", 88 "form-0-1-id": u"2", 89 "form-0-1-title": u"Need a title.", 90 "form-0-1-content": u"<p>Oldest content</p>", 91 "form-0-1-date_0": u"2000-03-18", 92 "form-0-1-date_1": u"11:54:58", 93 "form-0-2-id": u"3", 94 "form-0-2-title": u"Need a title.", 95 "form-0-2-content": u"<p>Newest content</p>", 96 "form-0-2-date_0": u"2009-03-18", 97 "form-0-2-date_1": u"11:54:58", 98 "form-0-3-id": u"", 99 "form-0-3-title": u"", 100 "form-0-3-content": u"", 101 "form-0-3-date_0": u"", 102 "form-0-3-date_1": u"", 103 "form-0-4-id": u"", 104 "form-0-4-title": u"", 105 "form-0-4-content": u"", 106 "form-0-4-date_0": u"", 107 "form-0-4-date_1": u"", 108 "form-0-5-id": u"", 109 "form-0-5-title": u"", 110 "form-0-5-content": u"", 111 "form-0-5-date_0": u"", 112 "form-0-5-date_1": u"", 113 113 } 114 114 response = self.client.post('/test_admin/%s/admin_views/section/1/' % self.urlbit, post_data) 115 115 self.failUnlessEqual(response.status_code, 302) # redirect somewhere … … 687 687 post_data = { 688 688 "name": u"Test lærdommer", 689 689 # inline data 690 " chapter_set-TOTAL_FORMS": u"6",691 " chapter_set-INITIAL_FORMS": u"3",692 " chapter_set-0-id": u"1",693 " chapter_set-0-title": u"Norske bostaver æøå skaper problemer",694 " chapter_set-0-content": u"<p>Svært frustrerende med UnicodeDecodeError</p>",695 " chapter_set-1-id": u"2",696 " chapter_set-1-title": u"Kjærlighet.",697 " chapter_set-1-content": u"<p>La kjærligheten til de lidende seire.</p>",698 " chapter_set-2-id": u"3",699 " chapter_set-2-title": u"Need a title.",700 " chapter_set-2-content": u"<p>Newest content</p>",701 " chapter_set-3-id": u"",702 " chapter_set-3-title": u"",703 " chapter_set-3-content": u"",704 " chapter_set-4-id": u"",705 " chapter_set-4-title": u"",706 " chapter_set-4-content": u"",707 " chapter_set-5-id": u"",708 " chapter_set-5-title": u"",709 " chapter_set-5-content": u"",690 "form-0-TOTAL_FORMS": u"6", 691 "form-0-INITIAL_FORMS": u"3", 692 "form-0-0-id": u"1", 693 "form-0-0-title": u"Norske bostaver æøå skaper problemer", 694 "form-0-0-content": u"<p>Svært frustrerende med UnicodeDecodeError</p>", 695 "form-0-1-id": u"2", 696 "form-0-1-title": u"Kjærlighet.", 697 "form-0-1-content": u"<p>La kjærligheten til de lidende seire.</p>", 698 "form-0-2-id": u"3", 699 "form-0-2-title": u"Need a title.", 700 "form-0-2-content": u"<p>Newest content</p>", 701 "form-0-3-id": u"", 702 "form-0-3-title": u"", 703 "form-0-3-content": u"", 704 "form-0-4-id": u"", 705 "form-0-4-title": u"", 706 "form-0-4-content": u"", 707 "form-0-5-id": u"", 708 "form-0-5-title": u"", 709 "form-0-5-content": u"", 710 710 } 711 711 712 712 response = self.client.post('/test_admin/admin/admin_views/book/1/', post_data) … … 721 721 self.failUnlessEqual(response.status_code, 200) 722 722 response = self.client.post('/test_admin/admin/admin_views/book/1/delete/', delete_dict) 723 723 self.assertRedirects(response, '/test_admin/admin/admin_views/book/') 724 725 class AdminInheritedInlinesTest(TestCase): 726 fixtures = ['admin-views-users.xml',] 727 728 def setUp(self): 729 self.client.login(username='super', password='secret') 730 731 def tearDown(self): 732 self.client.logout() 733 734 def testInlineInsert(self): 735 "Ensure that inline models which inherit from a common parent are correctly handled by admin." 736 737 foo_user = u"foo username" 738 bar_user = u"bar username" 739 740 post_data = { 741 "name": u"Test Name", 742 # inline data 743 "form-0-TOTAL_FORMS": u"1", 744 "form-0-INITIAL_FORMS": u"0", 745 "form-0-0-username": foo_user, 746 "form-1-TOTAL_FORMS": u"1", 747 "form-1-INITIAL_FORMS": u"0", 748 "form-1-0-username": bar_user, 749 } 750 751 response = self.client.post('/test_admin/admin/admin_views/persona/add/', post_data) 752 self.failUnlessEqual(response.status_code, 302) # redirect somewhere 753 self.failUnlessEqual(Persona.objects.count(), 1) 754 self.failUnlessEqual(FooAccount.objects.count(), 1) 755 self.failUnlessEqual(BarAccount.objects.count(), 1) 756 self.failUnlessEqual(FooAccount.objects.all()[0].username, foo_user) 757 self.failUnlessEqual(BarAccount.objects.all()[0].username, bar_user) 758 self.failUnlessEqual(Persona.objects.all()[0].accounts.count(), 2) 759 No newline at end of file -
tests/regressiontests/admin_views/models.py
134 134 class ThingAdmin(admin.ModelAdmin): 135 135 list_filter = ('color',) 136 136 137 class Persona(models.Model): 138 """ 139 A simple persona associated with accounts, to test inlining of related 140 accounts which inherit from a common accounts class. 141 """ 142 name = models.CharField(blank=False, max_length=80) 143 def __unicode__(self): 144 return self.name 145 146 class Account(models.Model): 147 """ 148 A simple, generic account encapsulating the information shared by all 149 types of accounts. 150 """ 151 username = models.CharField(blank=False, max_length=80) 152 persona = models.ForeignKey(Persona, related_name="accounts") 153 servicename = u'generic service' 154 155 def __unicode__(self): 156 return "%s: %s" % (self.servicename, self.username) 157 158 class FooAccount(Account): 159 """A service-specific account of type Foo.""" 160 servicename = u'foo' 161 162 class BarAccount(Account): 163 """A service-specific account of type Bar.""" 164 servicename = u'bar' 165 166 class FooAccountAdmin(admin.StackedInline): 167 model = FooAccount 168 169 class BarAccountAdmin(admin.StackedInline): 170 model = BarAccount 171 172 class PersonaAdmin(admin.ModelAdmin): 173 inlines = ( 174 FooAccountAdmin, 175 BarAccountAdmin 176 ) 177 137 178 admin.site.register(Article, ArticleAdmin) 138 179 admin.site.register(CustomArticle, CustomArticleAdmin) 139 180 admin.site.register(Section, inlines=[ArticleInline]) 140 181 admin.site.register(ModelWithStringPrimaryKey) 141 182 admin.site.register(Color) 142 183 admin.site.register(Thing, ThingAdmin) 184 admin.site.register(Persona, PersonaAdmin) 143 185 144 186 # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2. 145 187 # That way we cover all four cases: … … 153 195 admin.site.register(Book, inlines=[ChapterInline]) 154 196 admin.site.register(Promo) 155 197 admin.site.register(ChapterXtra1) 198 199 -
tests/regressiontests/generic_inline_admin/tests.py
51 51 post_data = { 52 52 "name": u"This Week in Django", 53 53 # inline data 54 " generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"1",55 " generic_inline_admin-media-content_type-object_id-INITIAL_FORMS": u"0",54 "form-0-TOTAL_FORMS": u"1", 55 "form-0-INITIAL_FORMS": u"0", 56 56 } 57 57 response = self.client.post('/generic_inline_admin/admin/generic_inline_admin/episode/add/', post_data) 58 58 self.failUnlessEqual(response.status_code, 302) # redirect somewhere … … 64 64 post_data = { 65 65 "name": u"This Week in Django", 66 66 # inline data 67 " generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"2",68 " generic_inline_admin-media-content_type-object_id-INITIAL_FORMS": u"1",69 " generic_inline_admin-media-content_type-object_id-0-id": u"%d" % self.media_pk,70 " generic_inline_admin-media-content_type-object_id-0-url": u"http://example.com/podcast.mp3",71 " generic_inline_admin-media-content_type-object_id-1-id": u"",72 " generic_inline_admin-media-content_type-object_id-1-url": u"",67 "form-0-TOTAL_FORMS": u"2", 68 "form-0-INITIAL_FORMS": u"1", 69 "form-0-0-id": u"%d" % self.media_pk, 70 "form-0-0-url": u"http://example.com/podcast.mp3", 71 "form-0-1-id": u"", 72 "form-0-1-url": u"", 73 73 } 74 74 url = '/generic_inline_admin/admin/generic_inline_admin/episode/%d/' % self.episode_pk 75 75 response = self.client.post(url, post_data)