SQLAlchemy - Упростить фильтр запросов с помощью Backref - PullRequest
0 голосов
/ 20 апреля 2020

Я использую Flask -SQLAlchemy в новом проекте, над которым я работаю, связанном с хранением инвентаря предметов пользователя во многих различных единицах хранения.

A User может владеть StorageLocation и что StorageLocation может содержать 1:n child StorageUnits. User может затем поделиться с кем-либо или полностью StorageLocation или только с отдельным StorageUnits - вот где я застрял.

Я пытаюсь написать запрос, чтобы найти все KitchenStorage объекты, к которым User имеет доступ (является ли он общим или принадлежащим).

Вот упомянутые классы -

shared_kitchen_members = db.Table(
    'shared_kitchens',
    db.Column('kitchen_id', db.Integer, db.ForeignKey('kitchen.id')),
    db.Column('user_id', db.Integer, db.ForeignKey('user.id'))
)

shared_kitchen_storage_members = db.Table(
    'shared_kitchen_storages',
    db.Column('kitchen_storage_id', db.Integer, db.ForeignKey('kitchen_storage.id')),
    db.Column('user_id', db.Integer, db.ForeignKey('user.id'))
)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    first_name = db.Column(db.String(64))
    last_name = db.Column(db.String(64))
    passowrd_hash = db.Column(db.String(128))
    owned_kitchens = db.relationship('Kitchen', backref='owner', lazy='dynamic')

    def __repr__(self):
        return f"<User: {self.username}>"

class Kitchen(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128))
    created = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    owner_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    shared_members = db.relationship('User', secondary=shared_kitchen_members,
        primaryjoin=(shared_kitchen_members.c.kitchen_id == id),
        secondaryjoin=(shared_kitchen_members.c.user_id == User.id),
        backref=db.backref('shared_kitchen', lazy='dynamic'), lazy='dynamic')
    kitchen_storages = db.relationship('KitchenStorage', backref='kitchen', lazy='dynamic')

    def __repr__(self):
        return f"<Kitchen: {self.name}>"

class KitchenStorage(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128))
    created = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    kitchen_id = db.Column(db.Integer, db.ForeignKey('kitchen.id'))
    shared_members = db.relationship('User', secondary=shared_kitchen_storage_members,
        primaryjoin=(shared_kitchen_storage_members.c.kitchen_storage_id == id),
        secondaryjoin=(shared_kitchen_storage_members.c.user_id == User.id),
        backref=db.backref('shared_kitchen_storage', lazy='dynamic'), lazy='dynamic')

    def __repr__(self):
        return f"<KitchenStorage: {self.name}>"

Это примеры запросов SQLAlchemy ORM, которые я написал, но я не уверен, есть ли лучший способ backref, чтобы очистить этот запрос.

# Show All Kitchen Storage (Owned or Shared by User 1)
owned = KitchenStorage.query.filter(KitchenStorage.kitchen_id.in_(u1.owned_kitchens.with_entities("id")))
shared = KitchenStorage.query.filter(KitchenStorage.kitchen_id.in_(u1.shared_kitchen.with_entities("id")))
owned_shared = owned.union(shared)
owned_shared.all()

Есть ли лучший способ получить доступ к этим объектам, кроме использования двух запросов и объединения на их, добавив лучше backref данных?

Спасибо!

...