Допустим, есть следующая простая структура данных:
Company(BaseModel):
id = AutoField()
# ...
User(BaseModel):
id = AutoField()
# ...
Delivery(BaseModel):
id = AutoField()
# peewee игнорирует lazy_load=True ?
manager = ForeignKeyField(User, backref='deliveries', lazy_load=True)
sender = ForeignKeyField(Company, backref='sender_deliveries')
receiver = ForeignKeyField(Company, backref='receiver_deliveries')
Когда необходимо запросить заказы с менеджерами, получателями и отправителями, предполагается следующий код:
select = Delivery.select().limit(3)
— Peewee в любом случае запросит все внешние связи, причем, экономными запросами по идентификаторам.
Но, допустим, нам требуется выбрать только отправителей.
select = Delivery.select(Delivery.id, ..., Delivery.sender).limit(3)
— приходится ограничивать поля Delivery. Этот способ теплее, но вместе с тем все связи Company будут загружены, включая, например, пользователя-автора записи с его паролем.
Более строгое ограничение не получится сделать (или я не нашел способ), если мы вручную не ограничим поля и не сделаем JOIN:
Sender = Company.alias()
Receiver = Company.alias()
select = Delivery.select(Delivery.id, Sender, Receiver, ...).limit(3)
select = select.join(Sender, JOIN.LEFT_OUTER, on=(Sender.id == Delivery.sender))
select = select.join(Receiver, JOIN.LEFT_OUTER, on=(Receiver.id == Delivery.receiver))
— во-первых, JOIN во многих случаях имеет больше расходов, во-вторых, в каком-то смысле ломается чистота кода, придется уделять много внимания менеджменту выборки полей и связей.
Документация хорошо рассматривает именно JOIN в разделе отношений, но как быть с "автоматической" выборкой по
ForeignKeyField? Хотелось бы обнаружить привычное with('sender'), но не вышло.
Есть ли способ изменять выборку без select(Model), join(Model)?