diff options
Diffstat (limited to 'docs/ref')
| -rw-r--r-- | docs/ref/checks.txt | 8 | ||||
| -rw-r--r-- | docs/ref/contrib/admin/actions.txt | 10 | ||||
| -rw-r--r-- | docs/ref/forms/fields.txt | 5 | ||||
| -rw-r--r-- | docs/ref/forms/widgets.txt | 18 | ||||
| -rw-r--r-- | docs/ref/models/conditional-expressions.txt | 10 | ||||
| -rw-r--r-- | docs/ref/models/fields.txt | 80 | ||||
| -rw-r--r-- | docs/ref/models/instances.txt | 10 |
7 files changed, 87 insertions, 54 deletions
diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index a208114596..cd539aa964 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -165,9 +165,11 @@ Model fields * **fields.E002**: Field names must not contain ``"__"``. * **fields.E003**: ``pk`` is a reserved word that cannot be used as a field name. -* **fields.E004**: ``choices`` must be an iterable (e.g., a list or tuple). -* **fields.E005**: ``choices`` must be an iterable containing ``(actual value, - human readable name)`` tuples. +* **fields.E004**: ``choices`` must be a mapping (e.g. a dictionary) or an + iterable (e.g. a list or tuple). +* **fields.E005**: ``choices`` must be a mapping of actual values to human + readable names or an iterable containing ``(actual value, human readable + name)`` tuples. * **fields.E006**: ``db_index`` must be ``None``, ``True`` or ``False``. * **fields.E007**: Primary keys must not have ``null=True``. * **fields.E008**: All ``validators`` must be callable. diff --git a/docs/ref/contrib/admin/actions.txt b/docs/ref/contrib/admin/actions.txt index f5f91982c1..263d43f8a3 100644 --- a/docs/ref/contrib/admin/actions.txt +++ b/docs/ref/contrib/admin/actions.txt @@ -47,11 +47,11 @@ news application with an ``Article`` model:: from django.db import models - STATUS_CHOICES = [ - ("d", "Draft"), - ("p", "Published"), - ("w", "Withdrawn"), - ] + STATUS_CHOICES = { + "d": "Draft", + "p": "Published", + "w": "Withdrawn", + } class Article(models.Model): diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt index 307ebb15a2..5e42404f94 100644 --- a/docs/ref/forms/fields.txt +++ b/docs/ref/forms/fields.txt @@ -510,8 +510,9 @@ For each field, we describe the default widget used if you don't specify .. versionchanged:: 5.0 - Support for using :ref:`enumeration types <field-choices-enum-types>` - directly in the ``choices`` was added. + Support for mappings and using + :ref:`enumeration types <field-choices-enum-types>` directly in + ``choices`` was added. ``DateField`` ------------- diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt index efff81ddbc..f76759b254 100644 --- a/docs/ref/forms/widgets.txt +++ b/docs/ref/forms/widgets.txt @@ -58,11 +58,11 @@ widget on the field. In the following example, the from django import forms BIRTH_YEAR_CHOICES = ["1980", "1981", "1982"] - FAVORITE_COLORS_CHOICES = [ - ("blue", "Blue"), - ("green", "Green"), - ("black", "Black"), - ] + FAVORITE_COLORS_CHOICES = { + "blue": "Blue", + "green": "Green", + "black": "Black", + } class SimpleForm(forms.Form): @@ -95,7 +95,7 @@ example: .. code-block:: pycon >>> from django import forms - >>> CHOICES = [("1", "First"), ("2", "Second")] + >>> CHOICES = {"1": "First", "2": "Second"} >>> choice_field = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES) >>> choice_field.choices [('1', 'First'), ('2', 'Second')] @@ -458,9 +458,9 @@ foundation for custom widgets. class DateSelectorWidget(forms.MultiWidget): def __init__(self, attrs=None): - days = [(day, day) for day in range(1, 32)] - months = [(month, month) for month in range(1, 13)] - years = [(year, year) for year in [2018, 2019, 2020]] + days = {day: day for day in range(1, 32)} + months = {month: month for month in range(1, 13)} + years = {year: year for year in [2018, 2019, 2020]} widgets = [ forms.Select(attrs=attrs, choices=days), forms.Select(attrs=attrs, choices=months), diff --git a/docs/ref/models/conditional-expressions.txt b/docs/ref/models/conditional-expressions.txt index d14312870f..cfdbd0790a 100644 --- a/docs/ref/models/conditional-expressions.txt +++ b/docs/ref/models/conditional-expressions.txt @@ -22,11 +22,11 @@ We'll be using the following model in the subsequent examples:: REGULAR = "R" GOLD = "G" PLATINUM = "P" - ACCOUNT_TYPE_CHOICES = [ - (REGULAR, "Regular"), - (GOLD, "Gold"), - (PLATINUM, "Platinum"), - ] + ACCOUNT_TYPE_CHOICES = { + REGULAR: "Regular", + GOLD: "Gold", + PLATINUM: "Platinum", + } name = models.CharField(max_length=50) registered_on = models.DateField() account_type = models.CharField( diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt index ff67312949..fbc90e5420 100644 --- a/docs/ref/models/fields.txt +++ b/docs/ref/models/fields.txt @@ -86,14 +86,26 @@ If a field has ``blank=False``, the field will be required. .. attribute:: Field.choices -A :term:`sequence` consisting itself of iterables of exactly two items (e.g. -``[(A, B), (A, B) ...]``) to use as choices for this field. If choices are -given, they're enforced by :ref:`model validation <validating-objects>` and the -default form widget will be a select box with these choices instead of the -standard text field. +A mapping or iterable in the format described below to use as choices for this +field. If choices are given, they're enforced by +:ref:`model validation <validating-objects>` and the default form widget will +be a select box with these choices instead of the standard text field. -The first element in each tuple is the actual value to be set on the model, -and the second element is the human-readable name. For example:: +If a mapping is given, the key element is the actual value to be set on the +model, and the second element is the human readable name. For example:: + + YEAR_IN_SCHOOL_CHOICES = { + "FR": "Freshman", + "SO": "Sophomore", + "JR": "Junior", + "SR": "Senior", + "GR": "Graduate", + } + +You can also pass a :term:`sequence` consisting itself of iterables of exactly +two items (e.g. ``[(A1, B1), (A2, B2), …]``). The first element in each tuple +is the actual value to be set on the model, and the second element is the +human-readable name. For example:: YEAR_IN_SCHOOL_CHOICES = [ ("FR", "Freshman"), @@ -103,6 +115,10 @@ and the second element is the human-readable name. For example:: ("GR", "Graduate"), ] +.. versionchanged:: 5.0 + + Support for mappings was added. + Generally, it's best to define choices inside a model class, and to define a suitably-named constant for each value:: @@ -115,13 +131,13 @@ define a suitably-named constant for each value:: JUNIOR = "JR" SENIOR = "SR" GRADUATE = "GR" - YEAR_IN_SCHOOL_CHOICES = [ - (FRESHMAN, "Freshman"), - (SOPHOMORE, "Sophomore"), - (JUNIOR, "Junior"), - (SENIOR, "Senior"), - (GRADUATE, "Graduate"), - ] + YEAR_IN_SCHOOL_CHOICES = { + FRESHMAN: "Freshman", + SOPHOMORE: "Sophomore", + JUNIOR: "Junior", + SENIOR: "Senior", + GRADUATE: "Graduate", + } year_in_school = models.CharField( max_length=2, choices=YEAR_IN_SCHOOL_CHOICES, @@ -142,6 +158,25 @@ will work anywhere that the ``Student`` model has been imported). You can also collect your available choices into named groups that can be used for organizational purposes:: + MEDIA_CHOICES = { + "Audio": { + "vinyl": "Vinyl", + "cd": "CD", + }, + "Video": { + "vhs": "VHS Tape", + "dvd": "DVD", + }, + "unknown": "Unknown", + } + +The key of the mapping is the name to apply to the group and the value is the +choices inside that group, consisting of the field value and a human-readable +name for an option. Grouped options may be combined with ungrouped options +within a single mapping (such as the ``"unknown"`` option in this example). + +You can also use a sequence, e.g. a list of 2-tuples:: + MEDIA_CHOICES = [ ( "Audio", @@ -160,17 +195,6 @@ be used for organizational purposes:: ("unknown", "Unknown"), ] -The first element in each tuple is the name to apply to the group. The -second element is an iterable of 2-tuples, with each 2-tuple containing -a value and a human-readable name for an option. Grouped options may be -combined with ungrouped options within a single list (such as the -``'unknown'`` option in this example). - -For each model field that has :attr:`~Field.choices` set, Django will add a -method to retrieve the human-readable name for the field's current value. See -:meth:`~django.db.models.Model.get_FOO_display` in the database API -documentation. - Note that choices can be any sequence object -- not necessarily a list or tuple. This lets you construct choices dynamically. But if you find yourself hacking :attr:`~Field.choices` to be dynamic, you're probably better off using @@ -180,6 +204,12 @@ meant for static data that doesn't change much, if ever. .. note:: A new migration is created each time the order of ``choices`` changes. +For each model field that has :attr:`~Field.choices` set, Django will normalize +the choices to a list of 2-tuples and add a method to retrieve the +human-readable name for the field's current value. See +:meth:`~django.db.models.Model.get_FOO_display` in the database API +documentation. + .. _field-choices-blank-label: Unless :attr:`blank=False<Field.blank>` is set on the field along with a diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt index 6bfd521aaa..6ceb0703ab 100644 --- a/docs/ref/models/instances.txt +++ b/docs/ref/models/instances.txt @@ -912,11 +912,11 @@ For example:: class Person(models.Model): - SHIRT_SIZES = [ - ("S", "Small"), - ("M", "Medium"), - ("L", "Large"), - ] + SHIRT_SIZES = { + "S": "Small", + "M": "Medium", + "L": "Large", + } name = models.CharField(max_length=60) shirt_size = models.CharField(max_length=2, choices=SHIRT_SIZES) |
