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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/sqlalchemy/8b32d287-1f74-4ebb-bc86-429fb3651effn%40googlegroups.com.