SQLAlchemy - 如何使用SQLAlchemy制作"django选择"?

pmo*_*niq 31 python sqlalchemy

在Django中,我们可以使用非常简单的"选择",例如:

GENDER_CHOICES = (
    ('M', 'Male'),
    ('F', 'Female'),
)
class Foo(models.Model):
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
Run Code Online (Sandbox Code Playgroud)

如何使用SQLAlchemy制作这样的东西?

est*_*tin 26

使用自定义类型.

例:

import sqlalchemy.types as types

class ChoiceType(types.TypeDecorator):

    impl = types.String

    def __init__(self, choices, **kw):
        self.choices = dict(choices)
        super(ChoiceType, self).__init__(**kw)

    def process_bind_param(self, value, dialect):
        return [k for k, v in self.choices.iteritems() if v == value][0]

    def process_result_value(self, value, dialect):
        return self.choices[value]
Run Code Online (Sandbox Code Playgroud)


rad*_*los 24

我可能会选择sqlalchemy_utils

  • 不幸的是,来自 sqlalchemy_utils 的 ChoiceType 分别破坏了版本 0.33.3 和 2.3 的 Flask-SQLAlchemy 迁移脚本。所以还有改进的空间。 (3认同)

Sym*_*ric 10

SQLAlchemy有一个Enum类型,其功能类似于Django的"选择"字段.

来自文档:

'Enum类型将使用后端的本机"ENUM"类型(如果有); 否则,它使用VARCHAR数据类型并生成CHECK约束.

import enum
class MyEnum(enum.Enum):
    one = 1
    two = 2
    three = 3


t = Table(
    'data', MetaData(),
    Column('value', Enum(MyEnum))
)

connection.execute(t.insert(), {"value": MyEnum.two})
assert connection.scalar(t.select()) is MyEnum.two
Run Code Online (Sandbox Code Playgroud)

  • 如果我错了,请纠正我:每次添加选项时是否都需要进行迁移? (3认同)
  • @tutuca你是100%正确的。使用枚举字段有一段时间了,另一个开发人员更改了 python 代码,但没有创建迁移,这带来了强烈的学习体验。 (3认同)
  • 与添加选项时的迁移相比,我更关心的是从枚举中删除值“不安全”(至少在 postgres 中)。https://www.postgresql.org/message-id/21012.1459434338%40sss.pgh.pa.us (2认同)