Ticket #16115: 16115.modeladmin-save-related.diff
File 16115.modeladmin-save-related.diff, 7.8 KB (added by , 13 years ago) |
---|
-
django/contrib/admin/options.py
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index c603210..a8ab3f3 100644
a b class ModelAdmin(BaseModelAdmin): 683 683 """ 684 684 formset.save() 685 685 686 def save_related(self, request, form, formsets, change): 687 """ 688 Given given the ``HttpRequest``, the parent ``ModelForm`` instance, 689 the list of inline formsets and a boolean value based on whether the 690 parent is being added or changed, save the related objects to the 691 database. Note that at this point save_form() and save_model() have 692 already been called. 693 """ 694 form.save_m2m() 695 for formset in formsets: 696 self.save_formset(request, form, formset, change=change) 697 686 698 def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): 687 699 opts = self.model._meta 688 700 app_label = opts.app_label … … class ModelAdmin(BaseModelAdmin): 886 898 prefix=prefix, queryset=inline.queryset(request)) 887 899 formsets.append(formset) 888 900 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) 893 901 self.save_model(request, new_object, form, False) 902 self.save_related(request, form, formsets, False) 894 903 self.log_addition(request, new_object) 895 904 return self.response_add(request, new_object) 896 905 else: … … class ModelAdmin(BaseModelAdmin): 988 997 formsets.append(formset) 989 998 990 999 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) 995 1000 self.save_model(request, new_object, form, True) 1001 self.save_related(request, form, formsets, True) 996 1002 change_message = self.construct_change_message(request, form, formsets) 997 1003 self.log_change(request, new_object, change_message) 998 1004 return self.response_change(request, new_object) -
docs/ref/contrib/admin/index.txt
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index e5aecb4..e8acae5 100644
a b templates used by the :class:`ModelAdmin` views: 949 949 instance.save() 950 950 formset.save_m2m() 951 951 952 .. method:: ModelAdmin.save_related(self, request, form, formsets, change) 953 954 .. versionadded:: 1.4 955 956 The ``save_related`` method is given the ``HttpRequest``, the parent 957 ``ModelForm`` instance, the list of inline formsets and a boolean value 958 based on whether the parent is being added or changed. Here you can do any 959 pre- or post-save operations for objects related to the parent. Note 960 that at this point the parent object and its form have already been saved. 961 952 962 .. method:: ModelAdmin.get_readonly_fields(self, request, obj=None) 953 963 954 964 .. versionadded:: 1.2 -
docs/releases/1.4.txt
diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt index 8742103..35a869d 100644
a b not custom filters. This has been rectified with a simple API previously 46 46 known as "FilterSpec" which was used internally. For more details, see the 47 47 documentation for :attr:`~django.contrib.admin.ModelAdmin.list_filter`. 48 48 49 ``ModelAdmin.save_related()`` 50 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 51 52 A new :meth:`~django.contrib.admin.ModelAdmin.save_related` hook was added to 53 :mod:`~django.contrib.admin.ModelAdmin` to ease the customization of how 54 related objects are saved in the admin. 55 49 56 Tools for cryptographic signing 50 57 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 51 58 -
tests/regressiontests/admin_views/models.py
diff --git a/tests/regressiontests/admin_views/models.py b/tests/regressiontests/admin_views/models.py index 854fb60..689ae0c 100644
a b class ChildInline(admin.StackedInline): 386 386 class ParentAdmin(admin.ModelAdmin): 387 387 model = Parent 388 388 inlines = [ChildInline] 389 390 def save_related(self, request, form, formsets, change): 391 super(ParentAdmin, self).save_related(request, form, formsets, change) 392 first_name, last_name = form.instance.name.split() 393 for child in form.instance.child_set.all(): 394 if len(child.name.split()) < 2: 395 child.name = child.name + ' ' + last_name 396 child.save() 389 397 390 398 class EmptyModel(models.Model): 391 399 def __unicode__(self): -
tests/regressiontests/admin_views/tests.py
diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py index 54d89e4..03db634 100644
a b from models import (Article, BarAccount, CustomArticle, EmptyModel, 37 37 Language, Collector, Widget, Grommet, DooHickey, FancyDoodad, Whatsit, 38 38 Category, Post, Plot, FunkyTag, Chapter, Book, Promo, WorkHour, Employee, 39 39 Question, Answer, Inquisition, Actor, FoodDelivery, 40 RowLevelChangePermissionModel, Paper, CoverLetter, Story, OtherStory) 40 RowLevelChangePermissionModel, Paper, CoverLetter, Story, OtherStory, 41 Parent, Child) 41 42 42 43 43 44 class AdminViewBasicTest(TestCase): … … class DateHierarchyTests(TestCase): 3001 3002 self.assert_non_localized_year(response, 2000) 3002 3003 self.assert_non_localized_year(response, 2003) 3003 3004 self.assert_non_localized_year(response, 2005) 3005 3006 class AdminCustomSaveRelatedTests(TestCase): 3007 """ 3008 Ensure that one can easily customise the way related objects are saved. 3009 Refs #16115. 3010 """ 3011 fixtures = ['admin-views-users.xml'] 3012 3013 def setUp(self): 3014 self.client.login(username='super', password='secret') 3015 3016 def test_should_be_able_to_edit_related_objects_on_add_view(self): 3017 post = { 3018 'child_set-TOTAL_FORMS': '3', 3019 'child_set-INITIAL_FORMS': '0', 3020 'name': 'Josh Stone', 3021 'child_set-0-name': 'Paul', 3022 'child_set-1-name': 'Catherine', 3023 } 3024 response = self.client.post('/test_admin/admin/admin_views/parent/add/', post) 3025 self.assertEqual(1, Parent.objects.count()) 3026 self.assertEqual(2, Child.objects.count()) 3027 3028 children_names = list(Child.objects.order_by('name').values_list('name', flat=True)) 3029 3030 self.assertEqual('Josh Stone', Parent.objects.latest('id').name) 3031 self.assertEqual([u'Catherine Stone', u'Paul Stone'], children_names) 3032 3033 def test_should_be_able_to_edit_related_objects_on_change_view(self): 3034 parent = Parent.objects.create(name='Josh Stone') 3035 paul = Child.objects.create(parent=parent, name='Paul') 3036 catherine = Child.objects.create(parent=parent, name='Catherine') 3037 post = { 3038 'child_set-TOTAL_FORMS': '5', 3039 'child_set-INITIAL_FORMS': '2', 3040 'name': 'Josh Stone', 3041 'child_set-0-name': 'Paul', 3042 'child_set-0-id': paul.id, 3043 'child_set-1-name': 'Catherine', 3044 'child_set-1-id': catherine.id, 3045 } 3046 response = self.client.post('/test_admin/admin/admin_views/parent/%s/' % parent.id, post) 3047 3048 children_names = list(Child.objects.order_by('name').values_list('name', flat=True)) 3049 3050 self.assertEqual('Josh Stone', Parent.objects.latest('id').name) 3051 self.assertEqual([u'Catherine Stone', u'Paul Stone'], children_names)