Re: [sqlalchemy] Mixins and lazy (query) attributes

2019-06-06 Thread Christian Barra


Il giorno mercoledì 5 giugno 2019 18:17:48 UTC+2, Mike Bayer ha scritto:
>
>
>
> On Wed, Jun 5, 2019, at 12:02 PM, Christian Barra wrote:
>
> Hi, I am trying to understand what the best approach is to have lazy 
> attributes defined on a mixin and then used them on the subclasses.
>
> Ideally I'd would like to defer the load of that attribute (controller) 
> and use `undefer` when I know that that attribute is needed, to execute 
> only one query.
>
> Below there's the code I am trying to use, `recipe_set` is a backref, same 
> for `unit`, Controller is another model.
>
>
> class BaseRecipeMixin(APIResourceMixin):
> _key = None
>
> @declared_attr
> def recipe_set_id(self):
> return db.Column(db.ForeignKey('recipe_set.id'), unique=True, 
> nullable=False)
>
> @property
> def controller(self):
> return column_property(
> Controller.query.filter(
> Controller.unit == self.recipe_set.unit,
> Controller.is_master.is_(True),
> Controller.is_deleted.is_(False),
> ).one_or_none(),
> deferred=True,
> )
>
>
> class EcRecipe(DosingRecipeMixin, BaseRecipeMixin, UpdateMixin, db.Model):
> id = db.Column(db.Integer, primary_key=True)
> pump_time = db.Column(db.Float, nullable=False, default=8)
>
>
> But when I try to run this
>
>
>
> when you declare mapped attributes on a mixin you have to use 
> @declared_attr:
>
>
> https://docs.sqlalchemy.org/en/13/orm/extensions/declarative/mixins.html#mixing-in-deferred-column-property-and-other-mapperproperty-classes
>
> The column_property() object needs to be made part of the mapping and 
> declarative uses this decorator to know it has to do that.
>
>
>
Thanks Mike, I'll try to use @declared_attr and go through the link.

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/a022c3d9-6d5d-4954-8b6d-9f947c4544d4%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [sqlalchemy] Mixins and lazy (query) attributes

2019-06-05 Thread Mike Bayer


On Wed, Jun 5, 2019, at 12:02 PM, Christian Barra wrote:
> Hi, I am trying to understand what the best approach is to have lazy 
> attributes defined on a mixin and then used them on the subclasses.
> 
> Ideally I'd would like to defer the load of that attribute (controller) and 
> use `undefer` when I know that that attribute is needed, to execute only one 
> query.
> 
> Below there's the code I am trying to use, `recipe_set` is a backref, same 
> for `unit`, Controller is another model.
> 
> 
> class BaseRecipeMixin(APIResourceMixin):
>  _key = None
> 
> @declared_attr
> def recipe_set_id(self):
> return db.Column(db.ForeignKey('recipe_set.id'), unique=True, nullable=False)
> 
> @property
> def controller(self):
> return column_property(
> Controller.query.filter(
> Controller.unit == self.recipe_set.unit,
> Controller.is_master.is_(True),
> Controller.is_deleted.is_(False),
> ).one_or_none(),
>  deferred=True,
> )
> 
> 
> class EcRecipe(DosingRecipeMixin, BaseRecipeMixin, UpdateMixin, db.Model):
>  id = db.Column(db.Integer, primary_key=True)
>  pump_time = db.Column(db.Float, nullable=False, default=8)
> 
> 
> But when I try to run this


when you declare mapped attributes on a mixin you have to use @declared_attr:

https://docs.sqlalchemy.org/en/13/orm/extensions/declarative/mixins.html#mixing-in-deferred-column-property-and-other-mapperproperty-classes

The column_property() object needs to be made part of the mapping and 
declarative uses this decorator to know it has to do that.





> 
> 
> models.EcRecipe.query.first().controller
> 
> 
> I get this error
> 
> Traceback (most recent call last):
> File 
> "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/code.py", 
> line 90, in runcode
> exec(code, self.locals)
> File "", line 1, in 
> File "/Users/cbarra/Projects/kompost/recipes/models.py", line 262, in 
> controller
>  deferred=True,
> File "", line 2, in column_property
> File "", line 2, in __init__
> File 
> "/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/util/deprecations.py",
>  line 130, in warned
> return fn(*args, **kwargs)
> File 
> "/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/properties.py",
>  line 134, in __init__
> self._orig_columns = [expression._labeled(c) for c in columns]
> File 
> "/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/properties.py",
>  line 134, in 
> self._orig_columns = [expression._labeled(c) for c in columns]
> File "", line 1, in 
> File 
> "/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/sql/elements.py",
>  line 4373, in _labeled
> return element.label(None)
> AttributeError: 'NoneType' object has no attribute 'label'
> 
> 
> while when I try to use `undefer` with
> 
> 
> models.EcRecipe.query.options(orm.undefer('controller'))
> 
> 
> the error is different
> 
> Traceback (most recent call last):
> File 
> "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/code.py", 
> line 90, in runcode
> exec(code, self.locals)
> File "", line 1, in 
> File 
> "/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/query.py",
>  line 1523, in options
> return self._options(False, *args)
> File "", line 2, in _options
> File 
> "/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/base.py",
>  line 220, in generate
>  fn(self, *args[1:], **kw)
> File 
> "/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/query.py",
>  line 1542, in _options
>  opt.process_query(self)
> File 
> "/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/strategy_options.py",
>  line 168, in process_query
> self._process(query, True)
> File 
> "/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/strategy_options.py",
>  line 542, in _process
>  raiseerr,
> File 
> "/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/strategy_options.py",
>  line 720, in _bind_loader
>  raiseerr,
> File 
> "/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/strategy_options.py",
>  line 235, in _generate_path
>  attr = found_property = attr.property
> AttributeError: 'property' object has no attribute 'property'
> 
> I am bit puzzled between property, hybrid_property and column_property, what 
> is the best way to have lazy attributes defined on a mixin?
> 

> --
>  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 

[sqlalchemy] Mixins and lazy (query) attributes

2019-06-05 Thread Christian Barra
Hi, I am trying to understand what the best approach is to have lazy 
attributes defined on a mixin and then used them on the subclasses.

Ideally I'd would like to defer the load of that attribute (controller) and 
use `undefer` when I know that that attribute is needed, to execute only 
one query.

Below there's the code I am trying to use, `recipe_set` is a backref, same 
for `unit`, Controller is another model.


class BaseRecipeMixin(APIResourceMixin):
_key = None

@declared_attr
def recipe_set_id(self):
return db.Column(db.ForeignKey('recipe_set.id'), unique=True, 
nullable=False)

@property
def controller(self):
return column_property(
Controller.query.filter(
Controller.unit == self.recipe_set.unit,
Controller.is_master.is_(True),
Controller.is_deleted.is_(False),
).one_or_none(),
deferred=True,
)


class EcRecipe(DosingRecipeMixin, BaseRecipeMixin, UpdateMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
pump_time = db.Column(db.Float, nullable=False, default=8)


But when I try to run this


models.EcRecipe.query.first().controller


I get this error

Traceback (most recent call last):
  File 
"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/code.py", 
line 90, in runcode
exec(code, self.locals)
  File "", line 1, in 
  File "/Users/cbarra/Projects/kompost/recipes/models.py", line 262, in 
controller
deferred=True,
  File "", line 2, in column_property
  File "", line 2, in __init__
  File 
"/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/util/deprecations.py"
, line 130, in warned
return fn(*args, **kwargs)
  File 
"/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/properties.py"
, line 134, in __init__
self._orig_columns = [expression._labeled(c) for c in columns]
  File 
"/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/properties.py"
, line 134, in 
self._orig_columns = [expression._labeled(c) for c in columns]
  File "", line 1, in 
  File 
"/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/sql/elements.py"
, line 4373, in _labeled
return element.label(None)
AttributeError: 'NoneType' object has no attribute 'label'


while when I try to use `undefer` with


models.EcRecipe.query.options(orm.undefer('controller'))


the error is different

Traceback (most recent call last):
  File 
"/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/code.py", 
line 90, in runcode
exec(code, self.locals)
  File "", line 1, in 
  File 
"/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/query.py"
, line 1523, in options
return self._options(False, *args)
  File "", line 2, in _options
  File 
"/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/base.py"
, line 220, in generate
fn(self, *args[1:], **kw)
  File 
"/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/query.py"
, line 1542, in _options
opt.process_query(self)
  File 
"/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/strategy_options.py"
, line 168, in process_query
self._process(query, True)
  File 
"/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/strategy_options.py"
, line 542, in _process
raiseerr,
  File 
"/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/strategy_options.py"
, line 720, in _bind_loader
raiseerr,
  File 
"/Users/cbarra/Projects/.venv/lib/python3.7/site-packages/sqlalchemy/orm/strategy_options.py"
, line 235, in _generate_path
attr = found_property = attr.property
AttributeError: 'property' object has no attribute 'property'

I am bit puzzled between property, hybrid_property and column_property, 
what is the best way to have lazy attributes defined on a mixin?

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/dd9354d6-5759-43f5-9fe4-b69f331e4822%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.