Skip to content

Commit

Permalink
Added check test to ensure that model field choices can not be callab…
Browse files Browse the repository at this point in the history
…les.
  • Loading branch information
nessita committed Aug 25, 2023
1 parent 61cacea commit b5d7a33
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 2 deletions.
6 changes: 4 additions & 2 deletions django/db/models/fields/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from django.db.models.constants import LOOKUP_SEP
from django.db.models.query_utils import DeferredAttribute, RegisterLookupMixin
from django.utils import timezone
from django.utils.choices import normalize_choices
from django.utils.choices import CallableChoiceIterator, normalize_choices
from django.utils.datastructures import DictWrapper
from django.utils.dateparse import (
parse_date,
Expand Down Expand Up @@ -315,7 +315,9 @@ def _check_choices(self):
if not self.choices:
return []

if not is_iterable(self.choices) or isinstance(self.choices, str):
if not is_iterable(self.choices) or isinstance(
self.choices, (str, CallableChoiceIterator)
):
return [
checks.Error(
"'choices' must be a mapping (e.g. a dictionary) or an iterable "
Expand Down
20 changes: 20 additions & 0 deletions tests/invalid_models_tests/test_ordinary_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,26 @@ class Model(models.Model):
],
)

def test_choices_callable(self):
def get_choices():
return [(i, i) for i in range(3)]

class Model(models.Model):
field = models.CharField(max_length=10, choices=get_choices)

field = Model._meta.get_field("field")
self.assertEqual(
field.check(),
[
Error(
"'choices' must be a mapping (e.g. a dictionary) or an iterable "
"(e.g. a list or tuple).",
obj=field,
id="fields.E004",
),
],
)

def test_bad_db_index_value(self):
class Model(models.Model):
field = models.CharField(max_length=10, db_index="bad")
Expand Down

0 comments on commit b5d7a33

Please sign in to comment.