我在表上有一个映射器,我想定义一个column_property,它应该选择True或False,无论该实体是否具有某些属性:
mapper( Person, persons_table, properties = {
'administrator': column_property(
select(
[True if roles_table.c.is_admin or roles_table.c.id == 1 else False],
roles_table.c.id == persons_table.c.role_id
).label( 'administrator' )
)
} )
这是我能做的吗?我对这部分更感兴趣:[True if roles_table.c.is_admin or roles_table.c.id == 1 else False],
,它允许我根据条件为列设置一个值。
答案 0 :(得分:3)
您的SELECT表达式实际上是一个Python表达式:
select([True if roles_table.c.is_admin or roles_table.c.id == 1 else False],
roles_table.c.id == persons_table.c.role_id)
sqlalchemy.select()
会将其视为:
select([True], some_expression_object)
因为列对象roles_table.c.is_admin
将在布尔上下文中计算为True
。我不知道SQLAlchemy将如何解释这一点,但它肯定不会像你想象的那样有效。
您必须使用sqlalchemy.sql.expression.case()
而不是if ... else ...
重写此表达式,使其与普通SQL相对应:
column_property(
select([case([(roles_table.c.is_admin, 1),
(roles_table.c.id == 1, 1)], else_=0)],
roles_table.c.id == persons_table.c.role_id))
但是,在您的情况下,可能会有一个更简单的解决方案。 Person
和Role
似乎有N:1
关系(一个人只有一个角色)。我假设有一个orm.relationship
Person.role
来获得一个人的角色。
为什么不添加普通的Python属性:
class Person:
# ...
@property
def administrator(self):
return self.role and (self.role.is_admin or self.role.id == 1)