99

Django モデルで ENUM を指定して使用するにはどうすればよいですか?

4

9 に答える 9

113

Djangoのドキュメントから:

MAYBECHOICE = (
    ('y', 'Yes'),
    ('n', 'No'),
    ('u', 'Unknown'),
)

そして、モデルで charfield を定義します:

married = models.CharField(max_length=1, choices=MAYBECHOICE)

データベースに文字を入れたくない場合は、整数フィールドでも同じことができます。

その場合は、選択内容を次のように書き直してください。

MAYBECHOICE = (
    (0, 'Yes'),
    (1, 'No'),
    (2, 'Unknown'),
)
于 2008-08-21T23:54:52.253 に答える
36
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) )
于 2009-10-07T10:47:46.560 に答える
35

パラメータを使用しchoicesても、ENUM db タイプは使用されません。choicesCharField または IntegerField のどちらで使用するかに応じて、VARCHAR または INTEGER を作成するだけです。通常、これで問題ありません。データベース レベルで ENUM 型を使用することが重要な場合は、次の 3 つのオプションがあります。

  1. "./manage.py sql appname" を使用して、Django が生成する SQL を確認し、手動で変更して ENUM 型を使用し、自分で実行します。最初にテーブルを手動で作成すると、"./manage.py syncdb" が台無しになりません。
  2. DB を生成するたびにこれを手動で行いたくない場合は、カスタム SQL を appname/sql/modelname.sql に配置して、適切な ALTER TABLE コマンドを実行します。
  3. カスタム フィールド タイプを作成し、db_type メソッドを適切に定義します。

これらのオプションのいずれかを使用する場合、データベース間の移植性への影響に対処するのはユーザーの責任です。オプション 2 では、データベース バックエンド固有のカスタム SQLを使用して、ALTER TABLE が MySQL でのみ実行されるようにすることができます。オプション 3 では、db_type メソッドでデータベース エンジンをチェックし、db 列の型をそのデータベースに実際に存在する型に設定する必要があります。

更新: Django 1.7 で移行フレームワークが追加されたため、上記のオプション 1 と 2 は完全に廃止されました。とにかく、オプション 3 は常に最良のオプションでした。オプション 1/2 の新しいバージョンには、 -- を使用した複雑なカスタム マイグレーションが含まれますSeparateDatabaseAndStateが、実際にはオプション 3 が必要です。

于 2008-08-29T03:57:14.687 に答える
10

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 つの優れた簡単な方法です。

ただし、「値」(数値の場合もある)を使用する必要がある最高評価の回答とは対照的に、デフォルトを照会または指定するたびに「ラベル」を参照できます。

于 2012-10-26T15:03:50.543 に答える
9

フィールドを設定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    |                |
+--------+-----------------------------+------+-----+---------+----------------+
于 2013-09-26T23:38:42.740 に答える
6

データベースの ENUM 型を本当に使用したい場合:

  1. Django 1.x を使用する
  2. アプリケーションが一部のデータベースでのみ機能することを認識してください。
  3. このドキュメンテーション ページをパズルしてください: http://docs.djangoproject.com/en/dev/howto/custom-model-fields/#howto-custom-model-fields

幸運を!

于 2008-12-02T18:21:16.663 に答える
3

現在、これらの追加に基づいた 2 つの github プロジェクトがありますが、それらがどのように実装されているかは正確には調べていません。

  1. Django-EnumField :
    列挙 Django モデル フィールド (IntegerField を使用) に、再利用可能な列挙型と遷移検証を提供します。
  2. Django-EnumFields :
    このパッケージを使用すると、Django で実際の Python (PEP435 スタイル) 列挙型を使用できます。

どちらも DB 列挙型を使用しているとは思いませんが最初のものは開発中です。

于 2015-02-09T11:23:31.483 に答える
-2

models.py ファイルの先頭に、インポートを行った後に次の行を追加します。

    enum = lambda *l: [(s,_(s)) for s in l]
于 2014-03-03T19:18:56.257 に答える