I guess I could do that: I am using a joined table inheritance schema for 
most of the classes in my data model (and that base table does have an 
entity_type_id) but was trying to link a few "entity_type"s to some of the 
classes that didn't inherit from the base.

The difference in the Django model is that the joined class (Addresses) has 
a parent_id column on it, and this line is key: "*class_.id* == foreign(
remote(Address.parent_id))".  without some column on the parent class to 
map to in the primaryjoin clause the relationship function doesn't seem to 
work.  I don't think the discriminator there is necessary to create 
relationship because there IS a "pseudo foreign key", it just has no 
referential integrity.  A bit of a digression but I can't really tell what 
the where clause part is necessary for tbh (Address.discriminator == 
discriminator). When would class_.id == Address.parent_ id but the class 
name != Address.discriminator?

 It would be nice if you could somehow override it and directly specify how 
to create the relationship with a custom query, but oh well...


On Monday, March 16, 2020 at 1:50:27 PM UTC-4, Mike Bayer wrote:
>
>
>
> On Mon, Mar 16, 2020, at 1:23 PM, Mark Aquino wrote:
>
> Unfortunately none of those recipes work for what I'm trying to 
> accomplish, and the mapper just complains that there is no "unambiguous" 
> foreign key column to map the two classes.
>
> Normal referential integrity rules would dictate that I create a column on 
> the related class that referred to the entity_type.id, but in a 
> non-polymorphic/shared table setting it seems completely unnecessary.: what 
> is the point in having a column on a single table like called 
> "entity_type_id" that has the same value in every row?  
>
> I need the relationship to be constructed by a query that looks like:
>
> select entity_type.*, something.*
> from entity_type, something
> where entity_type.table_name = 'something';
>
>
> would you perhaps want to use joined table inheritance?  that's the kind 
> of query it emits.   however the structure you gave does seem to be 
> equivalent to Django's generic foreign key to me.     the "table_name" is 
> known as the "discriminator".   
>
>
>
> or 
> select something.*, (select * from entity_type where 
> entity_type.table_name='something') from something;
>
> Is it impossible to create a relationship like this using sqlalchemy?
>
> sqlalchemy doesn't allow this:
>
> @event.listens_for(GenericEntityTypeMixin, "mapper_configured", 
> propagate=True)
> def setup_listener(mapper, class_):
>     discriminator = class_.__tablename__
>     class_.comments = relationship(
>         "EntityType",
>         primaryjoin=
>         foreign(remote(EntityType.table_name)) == discriminator
>         ,
>         viewonly=True
>     )
>
> On Saturday, March 14, 2020 at 12:55:03 PM UTC-4, Mike Bayer wrote:
>
> this is called a "Generic foreign key" and it's not really a real 
> relational database pattern.    There are a series of examples in 
> https://docs.sqlalchemy.org/en/13/orm/examples.html#module-examples.generic_associations
>  
> that show four different ways to achieve this pattern, one of which is the 
> "generic foreign key" that is for example what Django offers, where the 
> combination of a "discriminator" (here you call it table_name) and an id 
> can link to different source tables.   However there are three other ways 
> given of doing the same thing that all use correct referential integrity. 
>    Which one to use depends on how you need to be querying the 
> "entity_type"  table, however all four will store essentially the same 
> information, just in different formats.
>
>
>
>
>
>
>
> On Sat, Mar 14, 2020, at 9:55 AM, Mark Aquino wrote:
>
> Is it possible to create a relationship via the table name as the "foreign 
> key"? I tried playing around with the foreign and remote options and tried 
> utilizing what's described here: 
> https://docs.sqlalchemy.org/en/13/orm/join_conditions.html#non-relational-comparisons-materialized-path
>  but 
> I couldn't get it to work for my case.
>
> I have a table that has entity types and a table_name column, e.g.
>
> class EntityType(Base):
>     __tablename__ = "entity_type"
>     id = Column(UUID, primary_key=True, server_default=FetchedValue())
>     table_name = Column(String, nullable=False)
>     prefix = Column(Text, unique=True, nullable=False)
>     alt_prefix = Column(Text)
>     ui_label = Column(Text, unique=True, nullable=False)
>     entry_key = Column(Text, unique=True, nullable=False)
>
>     config_entity_column_ui_visibility = 
> relationship("ConfigEntityColumnUiVisibility")
>
>     def __repr__(self):
>         return (
>             f"<EntityType(id={self.id} table_name={self.table_name} 
> prefix={self.prefix} ui_label={self.ui_label} "
>             f"entry_key={self.entry_key}>"
>         )
>
>
> I want to create a relationship to this table from other tables via their 
> table name rather than a column on the table.  Is this possible?
>
>
> e.g.
>
> class GenericEntityTypeMixin:
>
>     @declared_attr.cascading
>     def prefix(cls) -> ColumnProperty:
>         from webapp.database.orm.models import EntityType
>
>         return column_property(
>             select([EntityType.prefix])
>                 .where(EntityType.table_name == cls.__tablename__)
>                 .as_scalar(),
>             info={"key": "prefix"},
>         )
>
>     @hybrid_property
>     def qualified_id(self):
>         return f"{self.prefix}-{self.visible_id}"
>
>     
> *# @declared_attr*
> *    # def entity_type(cls) -> RelationshipProperty:*
> *    #     how do we create relationship without using a column object on the 
> foreign side?*
>     @declared_attr
>     def entity_type_entry_key(cls):
>         return association_proxy("entity_type", "entry_key")
>
>
> --
> 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 sqlal...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/d54d0af1-7e8e-44f1-8398-989b09b3ea8e%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/sqlalchemy/d54d0af1-7e8e-44f1-8398-989b09b3ea8e%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>
>
>
> --
> 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 sqlal...@googlegroups.com <javascript:>.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/49e3f953-68b2-4810-8002-7035386b8e39%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/sqlalchemy/49e3f953-68b2-4810-8002-7035386b8e39%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>
>
>

-- 
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 view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/fe8a2ca9-9ba7-45f5-b4f9-84d6ea43cea2%40googlegroups.com.

Reply via email to