On 02/06/2017 04:38 PM, Евгений Иванов wrote:
    why don't you use a relationship() with the bound parameter?
    there's a
    recipe for this
    at https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/GlobalFilter
    <https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/GlobalFilter>.

seems it's exactly what I need!

Two last questions:
1. Is it possible to specify "path" to get needed value from bound
param, so I can bind request instance for each query in my framework and
a model will get a value it needs. Something like:
|
favorite =relationship(
  User,
  primaryjoin=Book.id ==UserFavoriteBooks.book_id,
  secondaryjoin=and_(
    UserFavoriteBooks.user_id ==User.id,
    User.id ==bindparam("request",lambada req:req.user.id)
  )
)
|

query:
|
books =session.query(requested_class).params(request=request).all()


instead of params() I'd build a simple MapperOption that does what you need. a bindparam() can use a lambda but it doesn't accept an argument so that usage wouldn't work like that. Within your mapperoption you'd extract the req.user.id and add it to params(). You would need a MapperOption in any case if you wanted lazy loading to work (the recipe is a little intricate in this regard).


|

and wouldn't it break if some models doesn't specify any bindparam but I
bound it to query?

you can have parameters in params() that aren't used, but also you can look inside of query.column_descriptions to see if your entity is there.

That's all because I build query automatically in my framework base on
resource requested by user

2. Can I make a relationship that will result in bool value:
favorite = relationship(User, ...., collection_class=bool)?

well a "bool" is not a "collection". You can have a list of scalar values with the association proxy (https://docs.sqlalchemy.org/en/latest/orm/extensions/associationproxy.html#simplifying-scalar-collections) but that doesn't make much sense for a "bool" because there are only two possible values.

"favorite" here looks like you have a Book and you want a list of all the Users who have this book as a favorite? that would just be the list of User objects then...




Thanks

On Monday, February 6, 2017 at 10:44:42 PM UTC+3, Mike Bayer wrote:



    On 02/06/2017 01:45 PM, Евгений Иванов wrote:
    > By fake I mean the field is not present in db, but present in
    model and
    > calculated when model is loaded. Favorite is a fields for Book
    model and
    > can be represented by something similar to:
    >
    > class Book(Base):
    > id = Column(...)
    > name = Column(...)
    > favorite_for = relationship(User, secondary=UserFavoriteBooks,
    > backref=favorite_books)
    > @property
    > def favorite(self)
    > return request.user.id <http://request.user.id> in [u.id
    <http://u.id> for u in self.favorite_for]
    >
    > request is global here.
    >
    > But I wan't it to be calculated once model is loaded, I think that
    could
    > be achieved by column_property by select() with case() to check if
    > current user is in the favorite_for list.

    why don't you use a relationship() with the bound parameter?
    there's a
    recipe for this at
    https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/GlobalFilter
    <https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/GlobalFilter>.

      I guess it's a little more up-front code than the column_property()
    but once you have it, you get this cool effect:

         obj = session.query(MyObject).\
               options(WithFavoriteItem(request.params['favorite_id'])).\
               one()




      If column_property is not
    > refreshed for every query it will be fine for this example (since
    user
    > is the same in scope of one http request, so doesn't change during
    > session lifetime), but could be a problem for other models if I
    compare
    > (in where clause) to something with more dynamic nature.


    Well your immediate use case is per-request.   I'd propose YAGNI for
    the
    "what if? what if?" part of this because this is not really a common
    use
    case.


    I just wonder
    > if there is a mechanism in SQLAlchemy that allows to have model
    fields
    > that calculated at query time and can be configured before the
    query is
    > emitted.

    that's what we're doing here w/ both the column_property you were doing
    and the relationship.

    If you want the column and/or relationship loaded all at once when you
    do query(), and you're concerned it was already loaded, just do
    populate_existing() and that will load it no matter what.


    > I can extend my example: backend renders reply with list of users,
    for
    > each user there is a list of books they bought, and for each book
    there
    > is a favorite filed which tells if this book bought by this user is
    > marked as favorite for him:
    > [{
    > name: "John Doe",
    > books: [{
    > name: "foo",
    > favorite: true
    > },
    > {
    > name: "bar",
    > favorite: false
    > }
    > }]
    > },
    > {
    > name: "Jane Roe",
    > books: [{
    > name: "foo",
    > favorite: false
    > },
    > {
    > name: "bar",
    > favorite: true
    > }
    > }]
    >
    > On Monday, February 6, 2017 at 7:13:02 PM UTC+3, Mike Bayer wrote:
    >
    >
    >
    >     On 02/06/2017 11:02 AM, Евгений Иванов wrote:
    >     > I need a dynamically calculated column for my model.
    column_property
    >     > looks great for that, but problem here that it's compiled at
    time
    >     when
    >     > model is mapped and I need to provide some value for
    filtering at
    >     time
    >     > the request is executed. I thought that bindparam can solve
    that
    >     problem
    >     > for me, but found that topic:
    >     >
    >
    
https://bitbucket.org/zzzeek/sqlalchemy/issues/3620/new-query-doesnt-expire-column_property
    
<https://bitbucket.org/zzzeek/sqlalchemy/issues/3620/new-query-doesnt-expire-column_property>

    >
    
<https://bitbucket.org/zzzeek/sqlalchemy/issues/3620/new-query-doesnt-expire-column_property
    
<https://bitbucket.org/zzzeek/sqlalchemy/issues/3620/new-query-doesnt-expire-column_property>>

    >
    >     >
    >     >     this is not really a great way to use column_property as
    it is
    >     >     treated like any other persisted attribute, and is not
    reloaded
    >     >     unnecessarily.
    >
    >
    >     you can use column_property with a bound parameter it just wont
    >     normally
    >     be refreshed if you query for the same object again when it's
    already
    >     loaded.   it depends on what you want things to do.
    >
    >
    >     > |
    >     > User:
    >     >   id
    >     >   name
    >     >
    >     > Book:
    >     >   id
    >     >   name
    >     >
    >     > UserFavoriteBooks:
    >     >   user_id
    >     >   book_id
    >     > |
    >     >
    >     > So I have many-to-many relation between users and books to
    represent
    >     > list of favorite books for a user. Then some user queries a
    book
    >     from DB
    >     > and want to know if it's in his favorite list, so I need to
    query the
    >     > Book entry for db with some fake bool column "favorite"
    which is
    >     checked
    >     > over the current user (who performed the request). Is it
    possible
    >     to do
    >     > that in SQLAlchemy so the "favorite" fields is automatically
    >     filled with
    >     > correct value once I do a query for a Book?
    >
    >     what's a "fake" column?   if "favorite" is a column in
    >     UserFavoriteBooks
    >     you'd use the association object pattern, i dont see where the
    >     column_property/bind thing is used there.
    >
    >
    >
    >     >
    >     > BR, Evgeny
    >     >
    >     > --
    >     > 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
    <http://stackoverflow.com/help/mcve>
    >     <http://stackoverflow.com/help/mcve
    <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 [email protected] <javascript:>
    >     > <mailto:[email protected]
    <javascript:> <javascript:>>.
    >     > To post to this group, send email to [email protected]
    >     <javascript:>
    >     > <mailto:[email protected] <javascript:>>.
    >     > Visit this group at
    https://groups.google.com/group/sqlalchemy
    <https://groups.google.com/group/sqlalchemy>
    >     <https://groups.google.com/group/sqlalchemy
    <https://groups.google.com/group/sqlalchemy>>.
    >     > For more options, visit https://groups.google.com/d/optout
    <https://groups.google.com/d/optout>
    >     <https://groups.google.com/d/optout
    <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
    <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 [email protected] <javascript:>
    > <mailto:[email protected] <javascript:>>.
    > To post to this group, send email to [email protected]
    <javascript:>
    > <mailto:[email protected] <javascript:>>.
    > Visit this group at https://groups.google.com/group/sqlalchemy
    <https://groups.google.com/group/sqlalchemy>.
    > For more options, visit https://groups.google.com/d/optout
    <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 [email protected]
<mailto:[email protected]>.
To post to this group, send email to [email protected]
<mailto:[email protected]>.
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to