#31155 closed Bug (fixed)
Named groups in choices are not properly validated in case of non str typed values.
Reported by: | sakkada | Owned by: | Mariusz Felisiak |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 3.0 |
Severity: | Release blocker | Keywords: | choices |
Cc: | pope1ni | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
In case of using typed choices and string value to store it (in my case it is multiple values stored in char field as JSON) it is possible to catch error while run makemigrations
(_check_choices
error):
main.MultiValueFieldModel.multi_value_field_integer_with_grouped_choices: (fields.E005) 'choices' must be an iterable containing (actual value, human readable name) tuples.
Looking deeper into the django code, we see actual error message: 'int' object is not iterable
and it happens in this block of code (https://github.com/django/django/blob/aa6c620249bc8c2a6245c8d7b928b05e7e5e78fc/django/db/models/fields/__init__.py#L271-L275):
if self.max_length is not None and group_choices: choice_max_length = max( choice_max_length, *(len(value) for value, _ in group_choices if isinstance(value, str)), )
If we have CharField (any other with max_length defined) and grouped choices with non str typed values like:
choices=( ('one', ((1, 'One',), (11, 'Eleven',),),), ('two', ((2, 'Two',), (22, 'Twenty two',),),), )
we will have the situation, when max
function receives only one integer value (choice_max_length
), because (len(value) for value, _ in group_choices if isinstance(value, str))
will return empty generator, and that is why error 'int' object is not iterable
raises (max
function waits iterable if there is only one argument).
Code block:
choice_max_length = max( choice_max_length, *(len(value) for value, _ in group_choices if isinstance(value, str)), )
in this case works like:
choice_max_length = max( choice_max_length, *[], )
which is incorrect.
The simples solution is to add one additional argument to max
function, which will be usefull only in this partucular situation:
choice_max_length = max( choice_max_length, 0, *(len(value) for value, _ in group_choices if isinstance(value, str)), )
Change History (5)
comment:1 by , 5 years ago
Owner: | changed from | to
---|---|
Severity: | Normal → Release blocker |
Status: | new → assigned |
Triage Stage: | Unreviewed → Accepted |
comment:3 by , 5 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Thanks for this report. Regression in b6251956b69512bf230322bd7a49b629ca8455c6.