Ticket #10271: admin_formset_inheritance.3.diff

File admin_formset_inheritance.3.diff, 15.6 KB (added by Idan Gazit, 15 years ago)

Same as 2, includes tests

  • django/contrib/admin/options.py

     
    522522            else:
    523523                form_validated = False
    524524                new_object = self.model()
    525             for FormSet in self.get_formsets(request):
     525            for idx, FormSet in enumerate(self.get_formsets(request)):
    526526                formset = FormSet(data=request.POST, files=request.FILES,
    527527                                  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)
    529530                formsets.append(formset)
    530531            if all_valid(formsets) and form_validated:
    531532                self.save_model(request, new_object, form, change=False)
     
    547548                if isinstance(f, models.ManyToManyField):
    548549                    initial[k] = initial[k].split(",")
    549550            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)
    552553                formsets.append(formset)
    553554       
    554555        adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)), self.prepopulated_fields)
     
    608609            else:
    609610                form_validated = False
    610611                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)):
    612613                formset = FormSet(request.POST, request.FILES,
    613                                   instance=new_object)
     614                                  instance=new_object, prefix="form-%s" % idx)
    614615                formsets.append(formset)
    615616           
    616617            if all_valid(formsets) and form_validated:
     
    625626       
    626627        else:
    627628            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)
    630631                formsets.append(formset)
    631632       
    632633        adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj), self.prepopulated_fields)
  • django/contrib/contenttypes/generic.py

     
    291291    ct_field_name = "content_type"
    292292    ct_fk_field_name = "object_id"
    293293
    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):
    295296        opts = self.model._meta
    296297        self.instance = instance
    297298        self.rel_name = '-'.join((
     
    300301        ))
    301302        super(BaseGenericInlineFormSet, self).__init__(
    302303            queryset=self.get_queryset(), data=data, files=files,
    303             prefix=self.rel_name
     304            prefix=prefix or self.rel_name
    304305        )
    305306
    306307    def get_queryset(self):
  • tests/regressiontests/admin_views/tests.py

     
    99from django.utils.html import escape
    1010
    1111# local test models
    12 from models import Article, CustomArticle, Section, ModelWithStringPrimaryKey
     12from models import Article, CustomArticle, Section, ModelWithStringPrimaryKey, Persona, FooAccount, BarAccount
    1313
    1414class AdminViewBasicTest(TestCase):
    1515    fixtures = ['admin-views-users.xml', 'admin-views-colors.xml']
     
    6363        post_data = {
    6464            "name": u"Another Section",
    6565            # 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",
    6868        }
    6969        response = self.client.post('/test_admin/%s/admin_views/section/add/' % self.urlbit, post_data)
    7070        self.failUnlessEqual(response.status_code, 302) # redirect somewhere
     
    7676        post_data = {
    7777            "name": u"Test section",
    7878            # 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",
    8282            # there is no title in database, give one here or formset
    8383            # 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"",
    113113        }
    114114        response = self.client.post('/test_admin/%s/admin_views/section/1/' % self.urlbit, post_data)
    115115        self.failUnlessEqual(response.status_code, 302) # redirect somewhere
     
    687687        post_data = {
    688688            "name": u"Test lærdommer",
    689689            # 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"",
    710710        }
    711711
    712712        response = self.client.post('/test_admin/admin/admin_views/book/1/', post_data)
     
    721721        self.failUnlessEqual(response.status_code, 200)
    722722        response = self.client.post('/test_admin/admin/admin_views/book/1/delete/', delete_dict)
    723723        self.assertRedirects(response, '/test_admin/admin/admin_views/book/')
     724
     725class 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

     
    134134class ThingAdmin(admin.ModelAdmin):
    135135    list_filter = ('color',)
    136136
     137class 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
     146class 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
     158class FooAccount(Account):
     159    """A service-specific account of type Foo."""
     160    servicename = u'foo'
     161
     162class BarAccount(Account):
     163    """A service-specific account of type Bar."""
     164    servicename = u'bar'
     165
     166class FooAccountAdmin(admin.StackedInline):
     167    model = FooAccount
     168
     169class BarAccountAdmin(admin.StackedInline):
     170    model = BarAccount
     171
     172class PersonaAdmin(admin.ModelAdmin):
     173    inlines = (
     174        FooAccountAdmin,
     175        BarAccountAdmin
     176    )
     177
    137178admin.site.register(Article, ArticleAdmin)
    138179admin.site.register(CustomArticle, CustomArticleAdmin)
    139180admin.site.register(Section, inlines=[ArticleInline])
    140181admin.site.register(ModelWithStringPrimaryKey)
    141182admin.site.register(Color)
    142183admin.site.register(Thing, ThingAdmin)
     184admin.site.register(Persona, PersonaAdmin)
    143185
    144186# We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
    145187# That way we cover all four cases:
     
    153195admin.site.register(Book, inlines=[ChapterInline])
    154196admin.site.register(Promo)
    155197admin.site.register(ChapterXtra1)
     198
     199
  • tests/regressiontests/generic_inline_admin/tests.py

     
    5151        post_data = {
    5252            "name": u"This Week in Django",
    5353            # 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",
    5656        }
    5757        response = self.client.post('/generic_inline_admin/admin/generic_inline_admin/episode/add/', post_data)
    5858        self.failUnlessEqual(response.status_code, 302) # redirect somewhere
     
    6464        post_data = {
    6565            "name": u"This Week in Django",
    6666            # 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"",
    7373        }
    7474        url = '/generic_inline_admin/admin/generic_inline_admin/episode/%d/' % self.episode_pk
    7575        response = self.client.post(url, post_data)
Back to Top