I am trying to (programmatically) create partial views of existing 
SQLAlchemy models, using a metaclass.

A streamlined example, trying to get a subquery view on a model Foo with a 
relationship bar, would look something like that:

class Bar(db.Model):
id = db.Column(db.Integer, primary_key=True)
class Foo(db.Model):
id = db.Column(db.Integer, primary_key=True)
bar_id = db.Column(db.Integer, db.ForeignKey("bar.id"))
bar = db.relationship(Bar, backref='foos')
class FooViewMeta(type(db.Model)):
def __new__(mcs, name, bases, attrs):
attrs["__table__"] = (select(Foo)
.with_only_columns(Foo.id, Foo.bar_id, Foo.bar)
.subquery())
attrs["bar"] = Foo.__mapper__.relationships["bar"]
attrs["__mapper_args__"] = {"exclude_properties": ["bar"]}
return super().__new__(mcs, name, (db.Model,), attrs)

class FooView(metaclass=FooViewMeta):
pass


(Omitting exclude_properties gives me a warning about conflicting columns)

I am able to load FooView and access its bar property fine.

Unfortunately, if I run:
q = Foo.query.options(joinedload(Foo.bar),)
q.first()

I get the following error, which tells me that this is not a correct way to 
duplicate the mapper for that relationship:
<class 'sqlalchemy.exc.ArgumentError'>: Mapped class 
Mapper[FooView(anon_1)] does 
not apply to any of the root entities in this query, e.g. Mapper[Foo(foo)]. 
Please specify the full path from one of the root entities to the target 
attribute. 

Clearly, the re-use of this relationship is confusing the mapper, who tries 
to use the newer subquery model and fails.

Conversely, if I use:
attrs["bar"] = getattr(Foo, "bar")
The code works for 1-1 relationship, but fails for lazy 1-many…

*Is there a clean way to (programmatically) duplicate all relationship from 
an existing model, over to a new model (that targets the same table and 
selects a subset of columns as a subquery)?*

Note: unfortunately, I am not looking for polymorphic subclassing here (the 
"view" classes are a subset of columns, not rows), so it does not seem like 
I can use any of SQLAlchemy mapper options for that…

-- 
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/8b32d287-1f74-4ebb-bc86-429fb3651effn%40googlegroups.com.

Reply via email to