On Mon, Feb 5, 2018 at 8:50 AM, Mikhail Knyazev <hellish...@gmail.com> wrote:
> Hi,
>
> I got a model which has two relationships with same table through a
> secondary table. Relationships are differentiated by a value of a column in
> secondary table. Here is an example:
>
> class NewsLog:
>     # `User` foreign key
>     user_id = db.Column(db.Integer)
>     # 'News' foreign key
>     news_id = db.Column(db.Integer)
>     type_id = db.Column(db.Integer)
>     created = db.Column(db.DateTime)
>
> class News:
>     id = db.Column(db.Integer)
>     viewed_by = db.relationship('User', secondary=NewsLog,
>                                 primaryjoin='and_(NewsLog.news_id ==
> News.id, NewsLog.type_id == 1)',  # 1 - view action in NewsLog
>                                 secondaryjoin='User.id == NewsLog.user_id',
> viewonly=True)
>     edited_by = db.relationship('User', secondary=NewsLog,
>                                 primaryjoin='and_(NewsLog.news_id ==
> News.id, NewsLog.type_id == 2)',  # 2 - edit action in NewsLog
>                                 secondaryjoin='User.id == NewsLog.user_id',
> viewonly=True)
>
>
>
> I'm doing one complicated query on `News` and it's convenient to manually
> load `viewed_by` and `edited_by` `Users` at once (or I think so). So I join
> `NewsLog` and `User` like this:
>
> query = (session.query(News)
>          .outerjoin(NewsLog, and_(NewsLog.news_id == News.id,
>                                   or_(NewsLog.type_id == 1, NewsLog.type_id
> == 2))
>          .outerjoin(User, User.id == NewsLog.user_id))
>
>
> Now query got all the data to fill these relationships, but is there any way
> to let SQLAlchemy know about it?
> Adding `contains_eager(News.viewed_by)` and `contains_eager(News.edited_by)`
> options leads to same objects are being loaded for `viewed_by` and
> `edited_by`.
>
> Is it mandatory in this case to join `NewsLog` second time (with different
> join condition) for relationships to work properly?

you can join to NewsLog once, however you need to join to User on two
separate aliases, like

u1, u2 = aliased(User), aliased(User)
query(News).outerjoin(NewsLog, ...).outerjoin(u1, ...).outerjoin(u2,
...).options(contains_eager(News.viewed_by, alias=u1),
contains_eager(News.edited_by, alias=u2))



>
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
> description.
> ---
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To post to this group, send email to sqlalchemy@googlegroups.com.
> Visit this group at https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to