100

ここでチュートリアルを読んでいます: https://docs.djangoproject.com/en/1.5/ref/models/fields/#choices そして、ユーザーが生まれた月を選択できるボックスを作成しようとしています私が試したのは

 MONTH_CHOICES = (
    (JANUARY, "January"),
    (FEBRUARY, "February"),
    (MARCH, "March"),
    ....
    (DECEMBER, "December"),
)

month = CharField(max_length=9,
                  choices=MONTHS_CHOICES,
                  default=JANUARY)

これは正しいです?私が読んでいたチュートリアルでは、何らかの理由で最初に変数を作成したことがわかりました。

FRESHMAN = 'FR'
SOPHOMORE = 'SO'
JUNIOR = 'JR'
SENIOR = 'SR'

なぜ彼らはそれらの変数を作成したのですか? また、MONTHS_CHOICES は People と呼ばれるモデルにあるため、私が提供したコードは、「People」と呼ばれるデータベースに「Months Choices」列を作成し、ユーザーが月をクリックした後に生まれた月を示しますか?フォームを送信しますか?

4

7 に答える 7

84

Django3.0+ の場合は、使用しますmodels.TextChoices(列挙型についてはdocs-v3.0を参照してください) 。

from django.db import models

class MyModel(models.Model):
    class Month(models.TextChoices):
        JAN = '1', "JANUARY"
        FEB = '2', "FEBRUARY"
        MAR = '3', "MAR"
        # (...)

    month = models.CharField(
        max_length=2,
        choices=Month.choices,
        default=Month.JAN
    )

使用法::

>>> obj = MyModel.objects.create(month='1')
>>> assert obj.month == obj.Month.JAN == '1'
>>> assert MyModel.Month(obj.month).label == 'JANUARY'
>>> assert MyModel.objects.filter(month=MyModel.Month.JAN).count() >= 1
>>> assert MyModel.Month(obj.month).name == 'JAN'

>>> obj2 = MyModel(month=MyModel.Month.FEB)
>>> assert obj2.get_month_display() == obj2.Month(obj2.month).label

ラベルが「JANUARY」であることがわかっているとしましょう。名前「JAN」と値「1」を取得するにはどうすればよいでしょうか?

label = "JANUARY"
name = {i.label: i.name for i in MyModel.Month}[label]
print(repr(name))  # 'JAN'
value = {i.label: i.value for i in MyModel.Month}[label]
print(repr(value))  # '1'

個人的にはむしろ使いたいmodels.IntegerChoices

class MyModel(models.Model):
    class Month(models.IntegerChoices):
        JAN = 1, "JANUARY"
        FEB = 2, "FEBRUARY"
        MAR = 3, "MAR"
        # (...)

    month = models.PositiveSmallIntegerField(
        choices=Month.choices,
        default=Month.JAN
    )
于 2019-12-05T16:11:01.423 に答える
60

ドキュメントによると:

Field.choices

このフィールドの選択肢として使用する、正確に 2 つの項目 ([(A, B), (A, B) ...]) の iterable で構成される iterable (たとえば、リストまたはタプル)。これが指定されている場合、デフォルトのフォーム ウィジェットは、標準のテキスト フィールドではなく、これらの選択肢を持つ選択ボックスになります。

各タプルの最初の要素は格納される実際の値で、2 番目の要素は人間が判読できる名前です。

したがって、変数などを定義するか、モジュールを使用JANUARYして定義する必要があることを除いて、コードは正しいです。FEBRUARYcalendarMONTH_CHOICES

import calendar
...

class MyModel(models.Model):
    ...

    MONTH_CHOICES = [(str(i), calendar.month_name[i]) for i in range(1,13)]

    month = models.CharField(max_length=9, choices=MONTH_CHOICES, default='1')
于 2013-09-07T18:03:53.760 に答える
11

最もクリーンな解決策は、django-model-utilsライブラリを使用することです。

from model_utils import Choices

class Article(models.Model):
    STATUS = Choices('draft', 'published')
    status = models.CharField(choices=STATUS, default=STATUS.draft, max_length=20)

https://django-model-utils.readthedocs.io/en/latest/utilities.html#choices

于 2018-11-03T08:14:15.340 に答える
4

コードに裸の単語を含めることはできません。それが変数を作成した理由です (コードは で失敗しますNameError)。

あなたが提供したコードは、という名前のデータベーステーブルを作成しますmonth(さらに、djangoがそれに追加するプレフィックスは何でも)CharField.

ただし、必要な特定の選択肢を作成するためのより良い方法があります。以前のスタック オーバーフローの質問を参照してください。

import calendar
tuple((m, m) for m in calendar.month_name[1:])
于 2013-09-07T18:04:16.260 に答える