Ticket #16115: new_hook_save_model_and_relations_with_tests_and_docs.diff

File new_hook_save_model_and_relations_with_tests_and_docs.diff, 8.6 KB (added by Igor Sobreira, 6 years ago)
  • docs/ref/contrib/admin/index.txt

     
    949949                    instance.save()
    950950                formset.save_m2m()
    951951
     952.. method:: ModelAdmin.save_model_and_relations(self, request, obj, form, formsets, change)
     953
     954    .. versionadded:: 1.4
     955
     956    The ``save_model_and_relations`` method is given the ``HttpRequest``,
     957    a model instance, a ``ModelForm`` instance, a list of formsets where each one
     958    represent and inline group, and boolean value based on whether it is
     959    adding or changing the object.
     960   
     961    This method is the last step on ``add_view`` and ``change_view``, where is
     962    guaranteed that the object and all related inlines are already saved.
     963
    952964.. method:: ModelAdmin.get_readonly_fields(self, request, obj=None)
    953965
    954966    .. versionadded:: 1.2
  • django/contrib/admin/options.py

     
    683683        """
    684684        formset.save()
    685685
     686    def save_model_and_relations(self, request, obj, form, formsets, change):
     687        """
     688        Given a model instance, a bound form and a list of inline formsets
     689        save everything in to the database.
     690   
     691        At this point save_form() has already been called, so just
     692        form.save_m2m() needs to be called.
     693        """
     694        self.save_model(request, obj, form, change=change)
     695        form.save_m2m()
     696        for formset in formsets:
     697            self.save_formset(request, form, formset, change=change)
     698
    686699    def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
    687700        opts = self.model._meta
    688701        app_label = opts.app_label
     
    886899                                  prefix=prefix, queryset=inline.queryset(request))
    887900                formsets.append(formset)
    888901            if all_valid(formsets) and form_validated:
    889                 self.save_model(request, new_object, form, change=False)
    890                 form.save_m2m()
    891                 for formset in formsets:
    892                     self.save_formset(request, form, formset, change=False)
     902                self.save_model_and_relations(request, new_object, form, formsets, change=False)
    893903
    894904                self.log_addition(request, new_object)
    895905                return self.response_add(request, new_object)
     
    988998                formsets.append(formset)
    989999
    9901000            if all_valid(formsets) and form_validated:
    991                 self.save_model(request, new_object, form, change=True)
    992                 form.save_m2m()
    993                 for formset in formsets:
    994                     self.save_formset(request, form, formset, change=True)
     1001                self.save_model_and_relations(request, new_object, form, formsets, change=True)
    9951002
    9961003                change_message = self.construct_change_message(request, form, formsets)
    9971004                self.log_change(request, new_object, change_message)
  • tests/regressiontests/admin_views/tests.py

     
    3737    Language, Collector, Widget, Grommet, DooHickey, FancyDoodad, Whatsit,
    3838    Category, Post, Plot, FunkyTag, Chapter, Book, Promo, WorkHour, Employee,
    3939    Question, Answer, Inquisition, Actor, FoodDelivery,
    40     RowLevelChangePermissionModel, Paper, CoverLetter, Story, OtherStory)
     40    RowLevelChangePermissionModel, Paper, CoverLetter, Story, OtherStory,
     41    Parent, Child)
    4142
    4243
    4344class AdminViewBasicTest(TestCase):
     
    30013002            self.assert_non_localized_year(response, 2000)
    30023003            self.assert_non_localized_year(response, 2003)
    30033004            self.assert_non_localized_year(response, 2005)
     3005
     3006class AdminHooksTests(TestCase):
     3007    fixtures = ['admin-views-users.xml']
     3008   
     3009    def setUp(self):
     3010        self.client.login(username='super', password='secret')
     3011   
     3012    def test_should_be_able_to_edit_related_objects_on_add_view(self):
     3013        post = {
     3014            'child_set-TOTAL_FORMS': '3',
     3015            'child_set-INITIAL_FORMS': '0',
     3016            'name': 'Josh Stone',
     3017            'child_set-0-name': 'Paul',
     3018            'child_set-1-name': 'Catherine',
     3019        }
     3020        response = self.client.post('/test_admin/admin/admin_views/parent/add/', post)
     3021        self.assertEqual(1, Parent.objects.count())
     3022        self.assertEqual(2, Child.objects.count())
     3023       
     3024        children_names = list(Child.objects.order_by('name').values_list('name', flat=True))
     3025       
     3026        self.assertEqual('Josh Stone', Parent.objects.latest('id').name)
     3027        self.assertEqual([u'Catherine Stone', u'Paul Stone'], children_names)
     3028   
     3029    def test_should_be_able_to_edit_related_objects_on_change_view(self):
     3030        parent = Parent.objects.create(name='Josh Stone')
     3031        paul = Child.objects.create(parent=parent, name='Paul')
     3032        catherine = Child.objects.create(parent=parent, name='Catherine')
     3033        post = {
     3034            'child_set-TOTAL_FORMS': '5',
     3035            'child_set-INITIAL_FORMS': '2',
     3036            'name': 'Josh Stone',
     3037            'child_set-0-name': 'Paul',
     3038            'child_set-0-id': paul.id,
     3039            'child_set-1-name': 'Catherine',
     3040            'child_set-1-id': catherine.id,
     3041        }
     3042        response = self.client.post('/test_admin/admin/admin_views/parent/%s/' % parent.id, post)
     3043       
     3044        children_names = list(Child.objects.order_by('name').values_list('name', flat=True))
     3045       
     3046        self.assertEqual('Josh Stone', Parent.objects.latest('id').name)
     3047        self.assertEqual([u'Catherine Stone', u'Paul Stone'], children_names)
     3048 No newline at end of file
  • tests/regressiontests/admin_views/models.py

     
    386386class ParentAdmin(admin.ModelAdmin):
    387387    model = Parent
    388388    inlines = [ChildInline]
     389   
     390    def save_model_and_relations(self, request, obj, form, formsets, change):
     391        super(ParentAdmin, self).save_model_and_relations(request, obj, form, formsets, change)
     392        first_name, last_name = obj.name.split()
     393        for child in obj.child_set.all():
     394            if len(child.name.split()) < 2:
     395                child.name = child.name + ' ' + last_name
     396                child.save()
    389397
    390398class EmptyModel(models.Model):
    391399    def __unicode__(self):
  • tests/regressiontests/modeladmin/tests.py

     
    302302        self.assertEqual(
    303303            list(ma.get_formsets(request))[0]().forms[0].fields.keys(),
    304304            ['extra', 'transport', 'id', 'DELETE', 'main_band'])
     305   
     306    def test_save_model_and_relations_should_call_save_model_and_save_formset(self):
     307        method_calls = {
     308            'save_model': [],
     309            'save_formset': [],
     310            'form.save_m2m': False
     311        }
     312        class BandAdmin(ModelAdmin):
     313            def save_model(self, request, obj, form, change):
     314                method_calls['save_model'] = (request, obj, form, change)
    305315
     316            def save_formset(self, request, form, formset, change):
     317                method_calls['save_formset'].append((request, form, formset, change))
    306318
     319        class FakeForm(object):
     320            def save_m2m(self):
     321                method_calls['form.save_m2m'] = True
     322
     323        request, obj, form, formset1, formset2 = object(), object, FakeForm(), object(), object()
     324
     325        band_admin = BandAdmin(Band, self.site)
     326        band_admin.save_model_and_relations(request, obj, form, [formset1,formset2], change=True)
     327
     328        self.assertTrue(1, len(method_calls['save_model']))
     329        self.assertTrue(2, len(method_calls['save_formset']))
     330        self.assertEqual((request, obj, form, True), method_calls['save_model'])
     331        self.assertTrue((request, form, formset1, True), method_calls['save_formset'][0])
     332        self.assertTrue((request, form, formset2, True), method_calls['save_formset'][1])
     333
     334
    307335class ValidationTests(unittest.TestCase):
    308336    def test_validation_only_runs_in_debug(self):
    309337        # Ensure validation only runs when DEBUG = True
Back to Top