Skip to content

Commit

Permalink
Validate PKs with to_python, added tests to verify validation errors …
Browse files Browse the repository at this point in the history
…are handled appropriately
  • Loading branch information
AdamDonna committed May 17, 2018
1 parent c750d8a commit d58d0ac
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 10 deletions.
12 changes: 7 additions & 5 deletions django/contrib/admin/options.py
Expand Up @@ -1592,13 +1592,15 @@ def get_edited_object_pks(self, request, prefix):

def get_list_editable_queryset(self, request, prefix):
object_pks = self.get_edited_object_pks(request, prefix)
modified_objects = self.get_queryset(request).filter(pk__in=object_pks)
queryset = self.get_queryset(request)
validate = queryset.model._meta.pk.to_python
try:
# Force evaluate queryset to verify that pks are valid
list(modified_objects)
for pk in object_pks:
validate(pk)
except ValidationError:
raise ValidationError("Invalid Primary Key Provided")
return modified_objects
# Disable optimization
return queryset
return queryset.filter(pk__in=object_pks)

@csrf_protect_m
def changelist_view(self, request, extra_context=None):
Expand Down
37 changes: 32 additions & 5 deletions tests/admin_changelist/tests.py
Expand Up @@ -763,11 +763,13 @@ def test_get_edited_object_ids(self):
pks = m.get_edited_object_pks(request, prefix='form')
self.assertEqual(sorted(pks), sorted([str(a.pk), str(b.pk), str(c.pk)]))

def test_type_error_on_invalid_pk_submission(self):
def test_validation_error_handled_on_invalid_pk_submission(self):
Swallow.objects.create(origin='Swallow A', load=4, speed=1)
Swallow.objects.create(origin='Swallow B', load=2, speed=2)

data = {
'form-TOTAL_FORMS': '3',
'form-INITIAL_FORMS': '3',
'form-TOTAL_FORMS': '2',
'form-INITIAL_FORMS': '2',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-uuid': 'INVALD_PRIMARY_KEY',
Expand All @@ -777,9 +779,34 @@ def test_type_error_on_invalid_pk_submission(self):
superuser = self._create_superuser('superuser')
self.client.force_login(superuser)
changelist_url = reverse('admin:admin_changelist_swallow_changelist')
m = SwallowAdmin(Swallow, custom_site)
request = self.factory.post(changelist_url, data=data)
queryset = m.get_list_editable_queryset(request, prefix='form')

self.assertEqual(queryset.count(), 2) # entire queryset returned on error

def test_queryset_limited_to_changed_objects(self):
a = Swallow.objects.create(origin='Swallow A', load=4, speed=1)
Swallow.objects.create(origin='Swallow B', load=2, speed=2)

data = {
'form-TOTAL_FORMS': '2',
'form-INITIAL_FORMS': '2',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-uuid': str(a.pk),
'form-0-load': 10,
'_save': 'Save',
}

superuser = self._create_superuser('superuser')
self.client.force_login(superuser)
changelist_url = reverse('admin:admin_changelist_swallow_changelist')
m = SwallowAdmin(Swallow, custom_site)
request = self.factory.post(changelist_url, data=data)
queryset = m.get_list_editable_queryset(request, prefix='form')

with self.assertRaisesMessage(ValidationError, "Invalid Primary Key Provided"):
self.client.post(changelist_url, data, follow=True, extra={'o': '-2'})
self.assertEqual(queryset.count(), 1)

def test_deterministic_order_for_unordered_model(self):
"""
Expand Down

0 comments on commit d58d0ac

Please sign in to comment.