On Fri, Jul 12, 2019, at 6:49 PM, Michael P. McDonnell wrote:
> Hey Mike - 
> 
> First off - thanks for the association proxy idea - I like that, and even if 
> heavy handed - specifically like the idea that its a *view* in to column as 
> opposed to a manipulable column. 
> The next question is - how do I iterate over those association proxy fields 
> within the object? 
> So if I'm to do a marshal to json - I'd like to say "my task has a name, 
> description, instructions, etc.."

the association proxy will show up in the mapping under all_orm_descriptors, 
e.g. 

from sqlalchemy import inspect

d = {
 k getattr(some_object, k) for k in 
inspect(some_object).mapper.all_orm_descriptors
}

https://docs.sqlalchemy.org/en/13/orm/mapping_api.html?highlight=all_orm_descriptors#sqlalchemy.orm.mapper.Mapper.all_orm_descriptors

> 
> On Fri, Jul 12, 2019 at 11:19 AM Mike Bayer <mike...@zzzcomputing.com> wrote:
>> __
>> 
>> 
>> On Fri, Jul 12, 2019, at 11:20 AM, Michael P. McDonnell wrote:
>>> Hey Team - 
>>> 
>>> So I'm working on a relatively fun hierarchy that allows me to relate tasks 
>>> to games. 
>>> So I have 2 tables:
>>> 
>>> # A Generic Task Definition - not related to anything
>>> class Task_Definition(Base):
>>>  def __repr__(self):
>>>  return (
>>>  "<TaskDefinition id='" + str(self.id) + "' "
>>>  + "name='" + self.name + "'>")
>>>  __table__ = task_definition_table # has name, id, etc...
>>> 
>>> # and a Task Table - specific to a game:
>>> class Task(Base):
>>>  def __repr__(self):
>>>  return (
>>>  "<Task id='" + str(self.id) + "' name='" + self.name
>>>  + "' game_id='" + str(self.game_id)
>>>  + " task_definition_id=" + str(self.task_definition_id) + "'>")
>>>  __table__ = task_table # has game_id, start_dttm, end_dttm, etc...
>>> 
>>> So originally I had my task as a 
>>> __table__ = join(task_definition_table, task_table)
>>> 
>>> That allowed me to select a task, and see all of the task_definition 
>>> properties as one "Object"
>>> But the problem is: when I created a task - it wanted to create a new 
>>> task_definition at the same time, which is not what I wanted - given that 
>>> task_definitions are a generic that can be used anytime.
>>> 
>>> So then I created a task like this:
>>> class Task(Base):
>>>  def __repr__(self):
>>>  return (
>>>  "<Task id='" + str(self.id) + "' name='" + self.name
>>>  + "' game_id='" + str(self.game_id)
>>>  + " task_definition_id=" + str(self.task_definition_id) + "'>")
>>>  __table__ = task_table
>>>  task_definition_id = column_property(
>>> task_definition_table.c.id,
>>>  task_definition_language_table.c.task_definition_id,
>>>  task_table.c.task_definition_id)
>>>  name = column_property(task_definition_language_table.c.name)
>>>  description = column_property(task_definition_language_table.c.description)
>>>  instructions = column_property(
>>>  task_definition_language_table.c.instructions)
>>> 
>>> That allowed me to insert properly - but then my selects were coming back 
>>> with tons of duplicate rows. 
>>> 
>>> When I played with the query - it was because it was doing a
>>> SELECT * from task, task_definition
>>> as opposed to a 
>>> select * from task JOIN task_definition...
>>> 
>>> Is there an easy way to force a join on select, and then a direct table 
>>> communication on insert?
>> 
>> So if you wanted to use column_property() like that, you would do it with a 
>> correlated select, as seen in the example at 
>> https://docs.sqlalchemy.org/en/13/orm/mapped_sql_expr.html#using-column-property.
>>  However, you have a whole bunch of them here and correlated selects aren't 
>> efficient from a SQL perspective. 
>> 
>> From the ORM point of view, exactly what you want is available using 
>> relationship() with lazy='joined':
>> 
>> class Task(Base):
>>  # ...
>> 
>>  description = relationship("TaskDefinition", lazy="joined")
>> 
>> But you don't want to say "mytask.description.name", OK. The data is in 
>> Python now so you can use all of Python's capabilities, in this case it 
>> would be to use descriptors:
>> 
>> class Task(Base):
>>  # ...
>> 
>>  @property
>>  def description(self):
>>  return self._description.description
>> 
>>  @description.setter # optional setter
>>  def description(self, value):
>>  self._description.description = value
>> 
>>  # etc ...
>> 
>>  _description = relationship("TaskDefinition", lazy="joined")
>> 
>> 
>> The above pattern is also available using the association proxy, which might 
>> be a little bit heavy-handed here, however is less code up front, 
>> association proxy is at 
>> https://docs.sqlalchemy.org/en/13/orm/extensions/associationproxy.html#:
>> 
>> from sqlalchemy.ext.associationproxy import association_proxy
>> 
>> class Task(Base):
>>  # ...
>>  description = association_proxy("_description", "description")
>> 
>>  # etc ...
>> 
>>  _description = relationship("TaskDefinition", lazy="joined")
>> 
>> 
>> hope this helps!
>> 
>> 
>> 
>> 
>> 
>>> 
>>> 
>>> -Mike
>>> 
>>> 

>>> --
>>> 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/328f63b3-dda4-4b59-a85b-52846e319d53%40googlegroups.com
>>>  
>>> <https://groups.google.com/d/msgid/sqlalchemy/328f63b3-dda4-4b59-a85b-52846e319d53%40googlegroups.com?utm_medium=email&utm_source=footer>.
>>> 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.
>>  To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/sqlalchemy/9429f760-5845-47cf-92b6-dee34e9f0c1c%40www.fastmail.com
>>  
>> <https://groups.google.com/d/msgid/sqlalchemy/9429f760-5845-47cf-92b6-dee34e9f0c1c%40www.fastmail.com?utm_medium=email&utm_source=footer>.
>>  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.
>  To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/CAHmCLHqFB-1spAzQd_VgCLChyaE%2BH5Pb94ymqXtaza6%3DyAbjVQ%40mail.gmail.com
>  
> <https://groups.google.com/d/msgid/sqlalchemy/CAHmCLHqFB-1spAzQd_VgCLChyaE%2BH5Pb94ymqXtaza6%3DyAbjVQ%40mail.gmail.com?utm_medium=email&utm_source=footer>.
>  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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/62388520-54b1-4f93-98e8-90050dbee9ea%40www.fastmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to