在Django模型中指定mySQL ENUM

时间:2020-03-05 18:41:50  来源:igfitidea点击:

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

解决方案

回答

从Django文档中:

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

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

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

如果我们不喜欢字母,可以对整数字段进行相同的操作
在数据库中。

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

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

回答

使用choices参数不会使用ENUM db类型。它只会创建VARCHAR或者INTEGER,这取决于我们是否将choices与CharField或者IntegerField一起使用。通常,这很好。如果在数据库级别使用ENUM类型对我们很重要,则有以下三种选择:

  • 使用" ./manage.py sql应用程序名称"查看Django生成的SQL,手动对其进行修改以使用ENUM类型,然后自行运行。如果我们首先手动创建该表,则" ./manage.py syncdb"将不会使它混乱。
  • 如果不想每次生成数据库时都手动执行此操作,请将一些自定义SQL放在appname / sql / modelname.sql中,以执行适当的ALTER TABLE命令。
  • 创建一个自定义字段类型,并适当地定义db_type方法。

使用这些选项中的任何一个,我们都有责任应对跨数据库可移植性的影响。在选项2中,可以使用特定于数据库后端的自定义SQL来确保ALTER TABLE仅在MySQL上运行。在选项3中,db_type方法将需要检查数据库引擎并将db列类型设置为该数据库中实际存在的类型。

更新:由于迁移框架是在Django 1.7中添加的,因此上述选项1和2完全过时了。无论如何,选择3始终是最好的选择。选项1/2的新版本将涉及使用SeparateDatabaseAndState进行复杂的自定义迁移-但实际上我们想要选项3.

回答

如果我们确实要使用数据库的ENUM类型,请执行以下操作:

  • 使用Django 1.x
  • 认识到应用程序仅适用于某些数据库。
  • 困惑于此文档页面:http://docs.djangoproject.com/en/dev/howto/custom-model-fields/#howto-custom-model-fields

祝你好运!

回答

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) )