'Can you modify relationship conditions in SQLAlchemy after initialization?

Overview

I'm working on a project which stores Artists in a database. Each time one or more artists are added to the database, a "transaction" is created for which the user can remove to undo that particular batch. Finally, each user can define one or more "profiles", storing separate lists of Artists in each (defined in var active_profile).

Using FKs with ondelete="CASCADE", when a Profile is deleted, all transactions are deleted and subsequently any artists belonging to those transactions are deleted.

active_profile = 2

class Profile(Base):
    __tablename__ = 'profile'

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

    def __init__(self, name):
        self.name = name

class Transaction(Base):
    __tablename__ = 'transaction'

    id = Column(Integer, primary_key=True)
    timestamp = Column(Integer, nullable=False)
    profile_id = Column(
                    Integer,
                    ForeignKey('profile.id', ondelete="CASCADE"),
                    nullable=False,
                 )
    artist = relationship(
                "Artist",
                cascade="delete",
                back_populates='transaction',
             )

    def __init__(self):
        self.timestamp = int(time.time())
        self.profile_id = active_profile

class Artist(Base):
    __tablename__ = 'artist'

    id = Column(Integer, primary_key=True)
    art_id = Column(Integer)
    art_name = Column(String)
    txn_id = Column(
                Integer,
                ForeignKey('transaction.id', ondelete="CASCADE"),
                nullable=False,
             )
    transaction = relationship("Transaction", back_populates="artist")

    def __init__(self, art_id, art_name, txn_id):
        self.art_id = art_id
        self.art_name = art_name
        self.txn_id = txn_id

The Goal

Most queries to the database will select where the profile_id is equal to the active_profile so I'm trying to figure out if there is a way to integrate this requirement into a relationship without having to specify it each time I query the database.


I have tried specifying primaryjoin in the relationship for the Transaction class but it seems to set the primaryjoin condition only once and doesn't change if active_profile is changed. I incorrectly assumed the relationship would be re-evaluated each time the class was called:

artist = relationship(
    "Artist",
    cascade="delete",
    back_populates="transaction",
    primaryjoin=f"and_(Transaction.id == Artist.txn_id, Transaction.profile_id == {active_profile}",
)

If this was re-evaluated each time, this would be exactly what I need.

Question

Is there a way to force the relationship to be re-evaluated and if not, is there any other option without the need to append .where(Transaction.profile_id == active_profile) to each query?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source