mirror of
https://github.com/django/django.git
synced 2025-10-24 06:06:09 +00:00
Fixed #20522 - Allowed use of partially validated object in ModelAdmin.add_view formset validation.
Updated ModelAdmin to use form.instance when passing parent model to child inlines for add_view. There is effectively no change in the change_view since the previously passed 'obj' is the same as form.instance. Thanks to meshy for report, and EvilDMP and timo for review.
This commit is contained in:
committed by
Tim Graham
parent
1c7a83ee8e
commit
c74504c2dd
@@ -51,7 +51,8 @@ from .models import (Article, BarAccount, CustomArticle, EmptyModel, FooAccount,
|
||||
AdminOrderedModelMethod, AdminOrderedAdminMethod, AdminOrderedCallable,
|
||||
Report, MainPrepopulated, RelatedPrepopulated, UnorderedObject,
|
||||
Simple, UndeletableObject, UnchangeableObject, Choice, ShortMessage,
|
||||
Telegram, Pizza, Topping, FilteredManager, City, Restaurant, Worker)
|
||||
Telegram, Pizza, Topping, FilteredManager, City, Restaurant, Worker,
|
||||
ParentWithDependentChildren)
|
||||
from .admin import site, site2, CityAdmin
|
||||
|
||||
|
||||
@@ -4597,7 +4598,7 @@ class TestLabelVisibility(TestCase):
|
||||
|
||||
|
||||
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
|
||||
class AdminViewOnSiteTest(TestCase):
|
||||
class AdminViewOnSiteTests(TestCase):
|
||||
urls = "admin_views.urls"
|
||||
fixtures = ['admin-views-users.xml', 'admin-views-restaurants.xml']
|
||||
|
||||
@@ -4607,6 +4608,64 @@ class AdminViewOnSiteTest(TestCase):
|
||||
def tearDown(self):
|
||||
self.client.logout()
|
||||
|
||||
def test_add_view_form_and_formsets_run_validation(self):
|
||||
"""
|
||||
Issue #20522
|
||||
Verifying that if the parent form fails validation, the inlines also
|
||||
run validation even if validation is contingent on parent form data
|
||||
"""
|
||||
# The form validation should fail because 'some_required_info' is
|
||||
# not included on the parent form, and the family_name of the parent
|
||||
# does not match that of the child
|
||||
post_data = {"family_name": "Test1",
|
||||
"dependentchild_set-TOTAL_FORMS": "1",
|
||||
"dependentchild_set-INITIAL_FORMS": "0",
|
||||
"dependentchild_set-MAX_NUM_FORMS": "1",
|
||||
"dependentchild_set-0-id": "",
|
||||
"dependentchild_set-0-parent": "",
|
||||
"dependentchild_set-0-family_name": "Test2"}
|
||||
response = self.client.post('/test_admin/admin/admin_views/parentwithdependentchildren/add/',
|
||||
post_data)
|
||||
|
||||
# just verifying the parent form failed validation, as expected --
|
||||
# this isn't the regression test
|
||||
self.assertTrue('some_required_info' in response.context['adminform'].form.errors)
|
||||
|
||||
# actual regression test
|
||||
for error_set in response.context['inline_admin_formset'].formset.errors:
|
||||
self.assertEqual(['Children must share a family name with their parents in this contrived test case'],
|
||||
error_set.get('__all__'))
|
||||
|
||||
def test_change_view_form_and_formsets_run_validation(self):
|
||||
"""
|
||||
Issue #20522
|
||||
Verifying that if the parent form fails validation, the inlines also
|
||||
run validation even if validation is contingent on parent form data
|
||||
"""
|
||||
pwdc = ParentWithDependentChildren.objects.create(some_required_info=6,
|
||||
family_name="Test1")
|
||||
# The form validation should fail because 'some_required_info' is
|
||||
# not included on the parent form, and the family_name of the parent
|
||||
# does not match that of the child
|
||||
post_data = {"family_name": "Test2",
|
||||
"dependentchild_set-TOTAL_FORMS": "1",
|
||||
"dependentchild_set-INITIAL_FORMS": "0",
|
||||
"dependentchild_set-MAX_NUM_FORMS": "1",
|
||||
"dependentchild_set-0-id": "",
|
||||
"dependentchild_set-0-parent": str(pwdc.id),
|
||||
"dependentchild_set-0-family_name": "Test1"}
|
||||
response = self.client.post('/test_admin/admin/admin_views/parentwithdependentchildren/%d/'
|
||||
% pwdc.id, post_data)
|
||||
|
||||
# just verifying the parent form failed validation, as expected --
|
||||
# this isn't the regression test
|
||||
self.assertTrue('some_required_info' in response.context['adminform'].form.errors)
|
||||
|
||||
# actual regression test
|
||||
for error_set in response.context['inline_admin_formset'].formset.errors:
|
||||
self.assertEqual(['Children must share a family name with their parents in this contrived test case'],
|
||||
error_set.get('__all__'))
|
||||
|
||||
def test_validate(self):
|
||||
"Ensure that the view_on_site value is either a boolean or a callable"
|
||||
CityAdmin.view_on_site = True
|
||||
|
||||
Reference in New Issue
Block a user