简体   繁体   中英

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. 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. So when a Task's status changes, I want to write task.statusName = 'working' instead of task.statusId = 3 . I'm not sure how to make a setter for statusName that does this. Is this against the design of an ORM, because the definition of the setter depends on the current rows present in the Status table?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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