如何使'标签'影响关系(column_property)

时间:2017-08-21 09:22:36

标签: python orm sqlalchemy flask-sqlalchemy

我正在使用Flask-SQLAlchemy开展一个项目。

模型如下所示: 汽车有组件, 组件可能有问题

car有一个column_property'inscess_repair',当汽车的组件出现问题时,这是真的

 needs_repair = column_property(exists().where(and_(
        carcomponent.columns['car_id'] == id,
        carcomponent.columns['component_id'] == componentissue.columns['component_id']
    )))

我为带有'skip'-column的标签添加了一个表,通过表iss_car_tag分配标签(忽略组件,仅引用特定的汽车发行关系)。

现在,如果所有已分配的标签都跳过了False或没有分配标签,我希望needs_repair为真

如何扩展column_property以实现此目的?

编辑: 型号/表定义:

class Component(Base):
    id = db.Column(db.Integer, primary_key=True)
    [...]
    issues = db.relationship('ISsue', secondary=componentissue, lazy='dynamic',
        back_populates='components')

    cars = db.relationship('Car', lazy = 'dynamic', secondary=carcomponent,
        back_populates="component"

    broken = column_property(exists().where(componentissue.columns['component_id'] == id))

class Car(Base):
   id = db.Column(db.Integer, primary_key=True)
   [...] 
   components = db.relationship('Component', secondary=carcomponent,
        back_populates="cars", lazy='dynamic')
   needs_repair = column_property(exists().where(and_(
            carcomponent.columns['car_id'] == id,
            carcomponent.columns['component_id'] == componentissue.columns['component_id']
        )))

class Issue(Base):
    __tablename__ = "issues"
    [...]    
    components = db.relationship('Component' lazy = 'dynamic', secondary=componentissue,
        back_populates='issues')

class Tag(Base):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text, unique=True)
    description = db.Column(db.Text, nullable=False, default="")
    skip = db.Column(db.Boolean, default = False)

class Issue_Car_Tag(Base):
    id = db.Column(db.Integer, primary_key=True)
    tag_id = db.Column(db.Integer, db.ForeignKey('tag.id'))
    car_id = db.Column(db.Integer, db.ForeignKey('car.id'))
    issue_id = db.Column(db.Integer, db.ForeignKey('issue.id'))
    tag = db.relationship('Tag', backref=db.backref('issue_car_tags'))
    car = db.relationship('Car',  backref=db.backref('issue_car_tags'))
    issue = db.relationship('Issue',  backref=db.backref('issue_car_tags'))

1 个答案:

答案 0 :(得分:1)

如果您在Tag和Issue_Car_Tag的定义之后移动Car的定义或以其他方式引用这些表,则可以生成以下查询构造

func.coalesce(func.bool_and(not_(Tag.skip)), False).\
    select().\
    where(Tag.id == Issue_Car_Tag.tag_id).\
    where(Issue_Car_Tag.car_id == id).\
    as_scalar()

并在现有支票的OR中使用它:

needs_repair = column_property(
    or_(func.coalesce(func.bool_and(not_(Tag.skip)), False).
            select().
            where(Tag.id == Issue_Car_Tag.tag_id).
            where(Issue_Car_Tag.car_id == id).
            as_scalar(),
        exists().where(and_(
            carcomponent.c.car_id == id,
            carcomponent.c.component_id == componentissue.c.component_id))))

查询使用关联表issue_car_tag和aggregates跳过值,coalescing空结果或所有空值选择与汽车相关的标签。

请注意,如果未分配任何标记,则会导致false,因此您必须单独处理。如果我已正确理解您的现有查询,则这已由您的EXISTS表达式处理。换句话说,如果标签存在并且所有标签都跳过设置为false,则新查询结果为true。