回答:
MAYBECHOICE = (
('y', 'Yes'),
('n', 'No'),
('u', 'Unknown'),
)
そして、あなたはあなたのモデルでcharfieldを定義します:
married = models.CharField(max_length=1, choices=MAYBECHOICE)
dbに文字を入れたくない場合は、整数フィールドでも同じことができます。
その場合は、選択内容を書き直してください。
MAYBECHOICE = (
(0, 'Yes'),
(1, 'No'),
(2, 'Unknown'),
)
from django.db import models
class EnumField(models.Field):
"""
A field class that maps to MySQL's ENUM type.
Usage:
class Card(models.Model):
suit = EnumField(values=('Clubs', 'Diamonds', 'Spades', 'Hearts'))
c = Card()
c.suit = 'Clubs'
c.save()
"""
def __init__(self, *args, **kwargs):
self.values = kwargs.pop('values')
kwargs['choices'] = [(v, v) for v in self.values]
kwargs['default'] = self.values[0]
super(EnumField, self).__init__(*args, **kwargs)
def db_type(self):
return "enum({0})".format( ','.join("'%s'" % v for v in self.values) )
使用するchoices
パラメータは、ENUMのDBタイプを使用することはありません。choices
CharFieldとIntegerFieldのどちらを使用するかに応じて、VARCHARまたはINTEGERを作成するだけです。通常、これで十分です。ENUMタイプをデータベースレベルで使用することが重要な場合は、3つのオプションがあります。
これらのオプションのいずれかを使用する場合、データベース間の移植性の影響に対処するのはユーザーの責任です。オプション2では、データベースバックエンド固有のカスタムSQLを使用して、ALTER TABLEがMySQLでのみ実行されるようにすることができます。オプション3では、db_typeメソッドでデータベースエンジンを確認し、dbカラムタイプをそのデータベースに実際に存在するタイプに設定する必要があります。
更新:Django 1.7で移行フレームワークが追加されたため、上記のオプション1と2は完全に廃止されました。とにかく、オプション3は常に最良のオプションでした。新しいバージョンのオプション1/2には、を使用した複雑なカスタム移行が含まれますSeparateDatabaseAndState
が、実際にはオプション3が必要です。
http://www.b-list.org/weblog/2007/nov/02/handle-choices-right-way/
class Entry(models.Model): LIVE_STATUS = 1 DRAFT_STATUS = 2 HIDDEN_STATUS = 3 STATUS_CHOICES = ( (LIVE_STATUS, 'Live'), (DRAFT_STATUS, 'Draft'), (HIDDEN_STATUS, 'Hidden'), ) # ...some other fields here... status = models.IntegerField(choices=STATUS_CHOICES, default=LIVE_STATUS) live_entries = Entry.objects.filter(status=Entry.LIVE_STATUS) draft_entries = Entry.objects.filter(status=Entry.DRAFT_STATUS) if entry_object.status == Entry.LIVE_STATUS:
これは、列挙を実際にデータベースに保存するわけではありませんが、列挙を実装するもう1つの優れた簡単な方法です。
ただし、「値」(数値の場合もあります)を使用する必要がある最高評価の回答とは対照的に、デフォルトを照会または指定するときはいつでも「ラベル」を参照できます。
choices
フィールドを設定すると、Django側である程度の検証が可能になりますが、データベース側で列挙型のフォームを定義することはできません。
他の人が述べたように、解決策はdb_type
カスタムフィールドで指定することです。
SQLバックエンド(MySQLなど)を使用している場合は、次のように実行できます。
from django.db import models
class EnumField(models.Field):
def __init__(self, *args, **kwargs):
super(EnumField, self).__init__(*args, **kwargs)
assert self.choices, "Need choices for enumeration"
def db_type(self, connection):
if not all(isinstance(col, basestring) for col, _ in self.choices):
raise ValueError("MySQL ENUM values should be strings")
return "ENUM({})".format(','.join("'{}'".format(col)
for col, _ in self.choices))
class IceCreamFlavor(EnumField, models.CharField):
def __init__(self, *args, **kwargs):
flavors = [('chocolate', 'Chocolate'),
('vanilla', 'Vanilla'),
]
super(IceCreamFlavor, self).__init__(*args, choices=flavors, **kwargs)
class IceCream(models.Model):
price = models.DecimalField(max_digits=4, decimal_places=2)
flavor = IceCreamFlavor(max_length=20)
を実行しsyncdb
、テーブルを調べて、ENUM
が正しく作成されたことを確認します。
mysql> SHOW COLUMNS IN icecream;
+--------+-----------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-----------------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| price | decimal(4,2) | NO | | NULL | |
| flavor | enum('chocolate','vanilla') | NO | | NULL | |
+--------+-----------------------------+------+-----+---------+----------------+
'type "enum" does not exist LINE 1: ....tablename" ADD COLUMN "select_user" ENUM('B', ...'
。
データベースのENUMタイプを本当に使いたい場合:
幸運を!
現在、これらの追加に基づいて2つのgithubプロジェクトがありますが、それらがどのように実装されているかは詳しく調べていません。
私はどちらもDB列挙型を使用することはないと思いますが、それらは最初のもののための作業中です。
ドキュメントから:
from django.utils.translation import gettext_lazy as _
class Student(models.Model):
class YearInSchool(models.TextChoices):
FRESHMAN = 'FR', _('Freshman')
SOPHOMORE = 'SO', _('Sophomore')
JUNIOR = 'JR', _('Junior')
SENIOR = 'SR', _('Senior')
GRADUATE = 'GR', _('Graduate')
year_in_school = models.CharField(
max_length=2,
choices=YearInSchool.choices,
default=YearInSchool.FRESHMAN,
)
ここで、データベースレベルでの選択を強制しないことに注意してください。これはPythonのみの構成です。これらの値をデータベースでも適用したい場合は、データベースの制約と組み合わせることができます。
class Student(models.Model):
...
class Meta:
constraints = [
CheckConstraint(
check=Q(year_in_school__in=YearInSchool.values),
name="valid_year_in_school")
]