New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refs #28458 -- Added validate_choices to ModelMultipleChoiceField. #14033
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gasparb16 Thanks for this patch 👍
@@ -1357,6 +1357,15 @@ generating choices. See :ref:`iterating-relationship-choices` for details. | |||
|
|||
.. _iterating-relationship-choices: | |||
|
|||
.. method:: ModelMultipleChoiceField.validate_choices(queryset, field_name, selected_choices) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be above the .. _iterating-relationship-choices:
. Also versionadded:: 4.0
annotation and release notes are missing, see #7181 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was not sure what the new use-case would be regarding the super() call, I would gladly accept some help with this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have a valid use case if we want to add a new hook 🤔 It can be used to avoid a queryset evaluation, but I'm not sure it's enough to justify adding it. It's really niche and was more of a workaround than a real need (see ticket-27148). I'm going to say wontfix
unless there's a more legitimate use-case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I understand, I just wanted to fix the issues in the PR and code some and if it is needed merge it. But I am fine with a wontfix that closes the ticket as well.
tests/model_forms/tests.py
Outdated
|
||
with self.assertNumQueries(1): | ||
field = CustomModelMultipleChoiceField(Category.objects.all()) | ||
with self.assertRaises(ValidationError) as exc: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use assertRaisesMessage()
.
tests/model_forms/tests.py
Outdated
def test_model_multiple_choice_field_validate_choices(self): | ||
with self.assertNumQueries(1): | ||
field = forms.ModelMultipleChoiceField(Category.objects.all()) | ||
with self.assertRaises(ValidationError) as exc: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use assertRaisesMessage()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if we can use this, because I would like to assert to the exc.exception.params not the message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, exc
-> cm
.
tests/model_forms/tests.py
Outdated
class CustomModelMultipleChoiceField(forms.ModelMultipleChoiceField, TestCase): | ||
def validate_choices(self, queryset, field_name, selected_choices): | ||
self.assertIsInstance(queryset, models.QuerySet) | ||
self.assertQuerysetEqual(queryset.order_by('id'), [1], lambda a: a.id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cannot make serial pk assumption:
diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py
index 8b54611010..ea68a105d6 100644
--- a/tests/model_forms/tests.py
+++ b/tests/model_forms/tests.py
@@ -1765,10 +1765,12 @@ class ModelMultipleChoiceFieldTests(TestCase):
f.clean([c6.id])
def test_model_multiple_choice_field_validate_choices_called_properly(self):
+ c1 = self.c1
+
class CustomModelMultipleChoiceField(forms.ModelMultipleChoiceField, TestCase):
def validate_choices(self, queryset, field_name, selected_choices):
self.assertIsInstance(queryset, models.QuerySet)
- self.assertQuerysetEqual(queryset.order_by('id'), [1], lambda a: a.id)
+ self.assertSequenceEqual(queryset, [c1])
self.assertIsInstance(field_name, str)
self.assertEqual(field_name, 'pk')
self.assertIsInstance(selected_choices, frozenset)
docs/ref/forms/fields.txt
Outdated
@@ -1357,6 +1357,15 @@ generating choices. See :ref:`iterating-relationship-choices` for details. | |||
|
|||
.. _iterating-relationship-choices: | |||
|
|||
.. method:: ModelMultipleChoiceField.validate_choices(queryset, field_name, selected_choices) | |||
|
|||
``validate_choices`` gets called with the filtered queryset (``queryset``), the name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
``validate_choices`` gets called with the filtered queryset (``queryset``), the name | |
``validate_choices`` gets called with the filtered ``queryset``, the name |
docs/ref/forms/fields.txt
Outdated
.. method:: ModelMultipleChoiceField.validate_choices(queryset, field_name, selected_choices) | ||
|
||
``validate_choices`` gets called with the filtered queryset (``queryset``), the name | ||
of the field, and the list of selected values. It should return the queryset. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
of the field, and the list of selected values. It should return the queryset. | |
of the field, and the list of selected values. It should return the queryset. |
docs/ref/forms/fields.txt
Outdated
of the field, and the list of selected values. It should return the queryset. | ||
|
||
The default implementation raises a ``ValidationError`` in case any of the | ||
``values`` is not in the list of attribute lookups of ``field_name`` in ``qs`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
`
``values`` is not in the list of attribute lookups of ``field_name`` in ``qs`` | |
``values`` is not in the list of attribute lookups of ``field_name`` in ``queryset`` |
df65fef
to
2137daf
Compare
Co-authored-by: blueyed <github@thequod.de>
2137daf
to
01285bd
Compare
@gasparb16 Thanks for your effort! 👍 Closing per ticket. |
I fixed the review findings from: #7181
Co-authored-by: blueyed github@thequod.de