在Django mod中指定mySQL枚举

2024-03-28 11:04:04 发布

您现在位置:Python中文网/ 问答频道 /正文


Tags: python
3条回答
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) )

Django documentation

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或整数,这取决于您是对CharField还是IntegerField使用choices。总的来说,这很好。如果在数据库级别使用枚举类型对您很重要,则有三个选项:

  1. 使用“./manage.py sql appname”查看sql Django生成的内容,手动修改它以使用枚举类型,然后自己运行它。如果首先手动创建表,“/manage.py syncdb”不会弄乱它。
  2. 如果不希望每次生成DB时都手动执行此操作,请在appname/SQL/modelname.SQL中放置一些自定义SQL以执行适当的ALTER TABLE命令。
  3. 创建一个custom field type并适当地定义db_type方法。

使用这些选项中的任何一个,您都有责任处理跨数据库可移植性的影响。在选项2中,可以使用database-backend-specific custom SQL来确保ALTER表只在MySQL上运行。在选项3中,db_type方法需要检查数据库引擎并将db列类型设置为该数据库中实际存在的类型。

更新:由于迁移框架是在Django 1.7中添加的,上面的选项1和2完全过时。无论如何,选择3总是最好的选择。选项1/2的新版本将使用SeparateDatabaseAndState进行复杂的自定义迁移,但实际上您需要选项3。

相关问题 更多 >