简体   繁体   English

从联接表查询的SQLAlchemy hybrid_property的设置方法

[英]Setter for a SQLAlchemy hybrid_property that queries from a joined table

I'm trying to model a task with a set of statuses in SQLAlchemy. 我正在尝试使用SQLAlchemy中的一组状态为任务建模。 I have the following: 我有以下内容:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship, backref

Base = declarative_base()

class Task(Base):
    __tablename__ = 'task'

    statusId = Column(Integer, ForeignKey('status.id'))
    status = relationship('Status', backref=backref('status'), lazy='joined')

    @hybrid_property
    def statusName(self):
        return self.status.name

class Status(Base):
    __tablename__ = 'status'

    id = Column(Integer, primary_key=True)
    name = Column(String(32), unique=True)

The status table is populated in the database and is fairly static: 状态表填充在数据库中,并且是静态的:

+----+--------------+
| id | name         |
+----+--------------+
|  1 | unassigned   |
|  2 | pending      |
|  3 | working      |
|  4 | failed       |
|  5 | done         |
+----+--------------+

What I want to be able to do is refer to the status names by name and not by id. 我想要做的是按名称而不是ID引用状态名称。 So when a Task's status changes, I want to write task.statusName = 'working' instead of task.statusId = 3 . 因此,当Task的状态更改时,我想编写task.statusName = 'working'而不是task.statusId = 3 I'm not sure how to make a setter for statusName that does this. 我不确定如何为此做一个statusName的setter。 Is this against the design of an ORM, because the definition of the setter depends on the current rows present in the Status table? 因为设置器的定义取决于Status表中当前的行,这是否违反了ORM的设计?

You could change your database structure slightly to achieve the intended effect. 您可以稍微更改数据库结构以达到预期的效果。 It seems that you have a natural key in status. 看来您的身份是自然的。 The name is effectively the primary key. 该名称实际上是主键。

class Task(Base):
    __tablename__ = 'task'

    status = Column(String(32), ForeignKey('status.name'))

class Status(Base):
    __tablename__ = 'status'

    name = Column(String(32), primary_key=True)

You could then easily set the status as such: 然后,您可以轻松地将状态设置为:

task = Task()
task.status = 'error'

This would also raise exceptions if the status was not available because there is still a foreign key constraint. 如果状态仍然不可用,因为仍然存在外键约束,这也会引发异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM