mirror of https://github.com/django/django.git
Fixed #16115 -- Added ModelAdmin.save_related method to be able to do pre- or post-save operations for objects related to the parent object currently displayed. Thanks, Julien Phalip.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16498 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
f9fe112f2d
commit
332a485567
|
@ -696,6 +696,18 @@ class ModelAdmin(BaseModelAdmin):
|
|||
"""
|
||||
formset.save()
|
||||
|
||||
def save_related(self, request, form, formsets, change):
|
||||
"""
|
||||
Given the ``HttpRequest``, the parent ``ModelForm`` instance, the
|
||||
list of inline formsets and a boolean value based on whether the
|
||||
parent is being added or changed, save the related objects to the
|
||||
database. Note that at this point save_form() and save_model() have
|
||||
already been called.
|
||||
"""
|
||||
form.save_m2m()
|
||||
for formset in formsets:
|
||||
self.save_formset(request, form, formset, change=change)
|
||||
|
||||
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
|
||||
opts = self.model._meta
|
||||
app_label = opts.app_label
|
||||
|
@ -899,11 +911,8 @@ class ModelAdmin(BaseModelAdmin):
|
|||
prefix=prefix, queryset=inline.queryset(request))
|
||||
formsets.append(formset)
|
||||
if all_valid(formsets) and form_validated:
|
||||
self.save_model(request, new_object, form, change=False)
|
||||
form.save_m2m()
|
||||
for formset in formsets:
|
||||
self.save_formset(request, form, formset, change=False)
|
||||
|
||||
self.save_model(request, new_object, form, False)
|
||||
self.save_related(request, form, formsets, False)
|
||||
self.log_addition(request, new_object)
|
||||
return self.response_add(request, new_object)
|
||||
else:
|
||||
|
@ -1001,11 +1010,8 @@ class ModelAdmin(BaseModelAdmin):
|
|||
formsets.append(formset)
|
||||
|
||||
if all_valid(formsets) and form_validated:
|
||||
self.save_model(request, new_object, form, change=True)
|
||||
form.save_m2m()
|
||||
for formset in formsets:
|
||||
self.save_formset(request, form, formset, change=True)
|
||||
|
||||
self.save_model(request, new_object, form, True)
|
||||
self.save_related(request, form, formsets, True)
|
||||
change_message = self.construct_change_message(request, form, formsets)
|
||||
self.log_change(request, new_object, change_message)
|
||||
return self.response_change(request, new_object)
|
||||
|
|
|
@ -978,6 +978,16 @@ templates used by the :class:`ModelAdmin` views:
|
|||
else:
|
||||
return ['name']
|
||||
|
||||
.. method:: ModelAdmin.save_related(self, request, form, formsets, change)
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
The ``save_related`` method is given the ``HttpRequest``, the parent
|
||||
``ModelForm`` instance, the list of inline formsets and a boolean value
|
||||
based on whether the parent is being added or changed. Here you can do any
|
||||
pre- or post-save operations for objects related to the parent. Note
|
||||
that at this point the parent object and its form have already been saved.
|
||||
|
||||
.. method:: ModelAdmin.get_readonly_fields(self, request, obj=None)
|
||||
|
||||
.. versionadded:: 1.2
|
||||
|
|
|
@ -80,6 +80,13 @@ to work similarly to how desktop GUIs do it. The new hook
|
|||
:meth:`~django.contrib.admin.ModelAdmin.get_ordering` for specifying the
|
||||
ordering dynamically (e.g. depending on the request) has also been added.
|
||||
|
||||
``ModelAdmin.save_related()``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A new :meth:`~django.contrib.admin.ModelAdmin.save_related` hook was added to
|
||||
:mod:`~django.contrib.admin.ModelAdmin` to ease the customization of how
|
||||
related objects are saved in the admin.
|
||||
|
||||
Tools for cryptographic signing
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -391,6 +391,14 @@ class ParentAdmin(admin.ModelAdmin):
|
|||
model = Parent
|
||||
inlines = [ChildInline]
|
||||
|
||||
def save_related(self, request, form, formsets, change):
|
||||
super(ParentAdmin, self).save_related(request, form, formsets, change)
|
||||
first_name, last_name = form.instance.name.split()
|
||||
for child in form.instance.child_set.all():
|
||||
if len(child.name.split()) < 2:
|
||||
child.name = child.name + ' ' + last_name
|
||||
child.save()
|
||||
|
||||
class EmptyModel(models.Model):
|
||||
def __unicode__(self):
|
||||
return "Primary key = %s" % self.id
|
||||
|
|
|
@ -38,7 +38,7 @@ from models import (Article, BarAccount, CustomArticle, EmptyModel,
|
|||
Category, Post, Plot, FunkyTag, Chapter, Book, Promo, WorkHour, Employee,
|
||||
Question, Answer, Inquisition, Actor, FoodDelivery,
|
||||
RowLevelChangePermissionModel, Paper, CoverLetter, Story, OtherStory,
|
||||
ComplexSortedPerson)
|
||||
ComplexSortedPerson, Parent, Child)
|
||||
|
||||
|
||||
class AdminViewBasicTest(TestCase):
|
||||
|
@ -3113,3 +3113,50 @@ class DateHierarchyTests(TestCase):
|
|||
self.assert_non_localized_year(response, 2000)
|
||||
self.assert_non_localized_year(response, 2003)
|
||||
self.assert_non_localized_year(response, 2005)
|
||||
|
||||
class AdminCustomSaveRelatedTests(TestCase):
|
||||
"""
|
||||
Ensure that one can easily customize the way related objects are saved.
|
||||
Refs #16115.
|
||||
"""
|
||||
fixtures = ['admin-views-users.xml']
|
||||
|
||||
def setUp(self):
|
||||
self.client.login(username='super', password='secret')
|
||||
|
||||
def test_should_be_able_to_edit_related_objects_on_add_view(self):
|
||||
post = {
|
||||
'child_set-TOTAL_FORMS': '3',
|
||||
'child_set-INITIAL_FORMS': '0',
|
||||
'name': 'Josh Stone',
|
||||
'child_set-0-name': 'Paul',
|
||||
'child_set-1-name': 'Catherine',
|
||||
}
|
||||
response = self.client.post('/test_admin/admin/admin_views/parent/add/', post)
|
||||
self.assertEqual(1, Parent.objects.count())
|
||||
self.assertEqual(2, Child.objects.count())
|
||||
|
||||
children_names = list(Child.objects.order_by('name').values_list('name', flat=True))
|
||||
|
||||
self.assertEqual('Josh Stone', Parent.objects.latest('id').name)
|
||||
self.assertEqual([u'Catherine Stone', u'Paul Stone'], children_names)
|
||||
|
||||
def test_should_be_able_to_edit_related_objects_on_change_view(self):
|
||||
parent = Parent.objects.create(name='Josh Stone')
|
||||
paul = Child.objects.create(parent=parent, name='Paul')
|
||||
catherine = Child.objects.create(parent=parent, name='Catherine')
|
||||
post = {
|
||||
'child_set-TOTAL_FORMS': '5',
|
||||
'child_set-INITIAL_FORMS': '2',
|
||||
'name': 'Josh Stone',
|
||||
'child_set-0-name': 'Paul',
|
||||
'child_set-0-id': paul.id,
|
||||
'child_set-1-name': 'Catherine',
|
||||
'child_set-1-id': catherine.id,
|
||||
}
|
||||
response = self.client.post('/test_admin/admin/admin_views/parent/%s/' % parent.id, post)
|
||||
|
||||
children_names = list(Child.objects.order_by('name').values_list('name', flat=True))
|
||||
|
||||
self.assertEqual('Josh Stone', Parent.objects.latest('id').name)
|
||||
self.assertEqual([u'Catherine Stone', u'Paul Stone'], children_names)
|
||||
|
|
Loading…
Reference in New Issue