如何在Django模型中指定和使用ENUM?

===============>>#1 票数:106

Django文档

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

然后在模型中定义一个charfield:

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

如果您不希望在数据库中包含字母,则可以对整数字段执行相同操作。

在这种情况下,重写您的选择:

MAYBECHOICE = (
    (0, 'Yes'),
    (1, 'No'),
    (2, 'Unknown'),
)

===============>>#2 票数: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) )

===============>>#3 票数:32

使用choices参数将不使用ENUM db类型; 它只是建立一个VARCHAR或INTEGER,这取决于您是否使用choices与CharField或IntegerField。 一般来说,这很好。 如果在数据库级别使用ENUM类型对您很重要,则有三个选项:

  1. 使用“./manage.py sql appname”查看SQL Django生成,手动修改它以使用ENUM类型,并自行运行。 如果您先手动创建表,“。/ manage.py syncdb”将不会乱用它。
  2. 如果您不希望每次生成数据库时手动执行此操作,请在appname / sql / modelname.sql中放置一些自定义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。

===============>>#4 票数:9

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: 

这是另一种实现枚举的简单方法,尽管它并没有真正保存数据库中的枚举。

但是,它允许您在查询或指定默认值时引用“标签”,而不是在必须使用“值”(可能是数字)的最高等级答案时。

===============>>#5 票数: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    |                |
+--------+-----------------------------+------+-----+---------+----------------+

===============>>#6 票数:6

如果你真的想使用你的数据库ENUM类型:

  1. 使用Django 1.x.
  2. 识别您的应用程序仅适用于某些数据库。
  3. 通过这个文档页面拼图: http//docs.djangoproject.com/en/dev/howto/custom-model-fields/#howto-custom-model-fields

祝好运!

===============>>#7 票数:3

目前有两个基于添加这些的github项目,但我还没有仔细研究它们是如何实现的:

  1. Django-EnumField
    提供枚举Django模型字段(使用IntegerField),具有可重用的枚举和转换验证。
  2. Django-EnumFields
    这个包允许你使用Django的真实Python(PEP435风格)枚举。

我不认为要么使用DB枚举类型,但他们的作品的第一个。

===============>>#8 票数:-2

在models.py文件的顶部,执行导入后添加以下行:

    enum = lambda *l: [(s,_(s)) for s in l]

  ask by Steve translate from so

未解决问题?本站智能推荐:

1回复

如何从模板中访问Django模型的枚举?

我的Django模型类别如下: 我将作为MyClass实例的my_instance传递到模板中。 在该模板中,如何对my_field的可能值进行if-else检查? 我执行以下操作,但是不起作用: 编辑:我可以将MyClass类传递到模板上下文中,然后使用MyClass.
2回复

MySQL将枚举值转换为整数值

我有一个表,其中包含一个带有值“ B”,“ N”,“ F”和“ V”的ENUM字段。 我想为每个字母分配一个权重: 这些权重应显示在select语句的列中。 最后,我想将这些值加在一起。 这可能吗? 目标是在Django中执行此操作,但使用MySQL也可以。
3回复

如何使用枚举作为django模型中的选择字段

我有一个模型类,我想要两个字段作为选择字段,所以要填充这些选项我使用枚举如下所示 但是,当我尝试通过管理员访问此模型时,我收到以下错误: 我跟着两篇描述如何使用枚举的文章: https://hackernoon.com/using-enum-as-model-field
2回复

Django枚举在函数中可见吗?

在我的模型中,我创建了一个枚举: 当我将其定义为choises =时,它在类中是可见的 但是我无法从模型的def中访问它:生成一些HTML以使其在我的表单中可用。 cs_review_goals或models.cs_review_goals均不起作用。 我想我很傻,在这里
1回复

枚举类字段更改时引发ValueError

枚举类 模型 我已更改枚举FREE_TEXT 之后,我尝试运行我的应用程序并引发Value Error 。 以及我也尝试运行python manage.py makemigrations (尽管据我所知并不需要)。 但这也给了我错误。 引发ValueErro
1回复

Django 1.8.2(使用Python 3.4):带有选择项的CharField如何存储在带有ENUM列的MySQL表中?

根据一个StackOverflow问题 ,一个答案说我可以在Django模型中指定一个模仿MySQL ENUM列功能的CharField。 假设我在models.py模块中声明了以下元组集: 现在,我有以下模型,该模型仅存储一个CharField,其中保存了我刚刚声明的元组集:
6回复

Django模型可以使用MySQL函数吗?

有没有办法强制Django模型在每次读取或加载模型数据时将字段传递给MySQL函数? 为了澄清我在SQL中的含义,我希望Django模型能够产生如下内容: 在模型加载时:SELECT AES_DECRYPT(fieldname,password)FROM tablename 在模型
2回复

在MySql服务器上导出Django模型

我将外部数据库导入到我的项目中,然后使用python manage.py inspectdb > models.py命令将其转换为models.py文件。 现在我通过添加另一个类来编辑models.py文件。 如何在不妨碍数据库中已存在的数据的情况下将models.py文件导出到M
3回复

在对Django模型进行平均时,为什么MYSQL DB返回损坏的值?

我正在MySQL(实际上是MariaDB)数据库之上运行Django应用程序。 我的Django模型如下所示: 当我运行get_stats() ,得到以下日志行: 我的问题是数据库返回的my_date字段的平均值为: 20080507582679.5 。 仔细看那个数字。
3回复

在尝试使用Django模型访问mysql视图时抛出错误

我想使用django过滤器访问mysql视图中的记录,但会引发错误 错误: