Как добавить автоматический фильтр к отношению с помощью SQLAlchemy?

StackOverflow https://stackoverflow.com/questions/267861

  •  06-07-2019
  •  | 
  •  

Вопрос

Я использую SQLAlchemy 0.5rc, и я хотел бы добавить автоматический фильтр к отношению, чтобы каждый раз, когда он пытался извлечь записи для этого отношения, он игнорировал "удаленные" записи, если они помечены как "logically_deleted" (логическое поле дочерней таблицы)

Например, если объект "родительский" имеет отношение "дочерний", которое имеет 3 записи, но одна из них логически удалена, когда я запрашиваю "Родительский", я бы хотел, чтобы SQLA извлекала родительский объект только с двумя дочерними объектами..
Как я должен это сделать?Путем добавления условия "и" к параметру primaryjoin отношения?(например,"Children.parent_id == Parent.id and Children.logically_deleted == False", но правильно ли писать "и" таким образом?)

Редактировать:
Мне удалось сделать это таким образом

children = relation("Children", primaryjoin=and_(id == Children.parent_id, Children.logically_deleted==False))

но есть ли способ использовать string в качестве primaryjoin вместо этого?

Это было полезно?

Решение

Функция and_() является правильным способом выполнения логических соединений в SQLAlchemy вместе с оператором &, но будьте осторожны с последним, поскольку он имеет неожиданные правила приоритета, т.е.более высокий приоритет, чем у операторов сравнения.

Вы также могли бы использовать строку в качестве основного соединения с конструктором text(), но это приведет к разрыву вашего кода при любом псевдонимировании таблицы, которое поставляется с eagerloading и joins.

Для логического удаления, возможно, было бы лучше сопоставить весь класс с select, который игнорирует удаленные значения:

mapper(Something, select([sometable], sometable.c.deleted == False))

Другие советы

но есть ли способ использовать string в качестве primaryjoin вместо этого?

Вы можете использовать следующее:

children = relationship("Children", primaryjoin="and_(Parent.id==Children.parent_id, Children.logically_deleted==False)"

У меня это сработало!

В настоящее время я разрабатываю только agains 0.4.something, но вот как я бы это предложил:

db.query(Object).filter(Object.first==value).filter(Object.second==False).all()

Я думаю, это то, что вы пытаетесь сделать, не так ли?

(Примечание:написано в веб-браузере, а не в реальном коде!)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top