the history of with_polymorphic spans back to the time when we didn't have
declarative and just the mapper() call was used, at which point any particular
subclass would also be available, and yes you certainly can pass a specific
list of classes to the mapper-level with_polymorphic - the with_polymorphic
argument on mapper() takes the exact same argument format as the
with_polymorphic() method on Query.
It's the declarative system that is not letting you do it, as this is not a
common use case, but the reason is because the hook you're using is called
during the creation of the Test class, necessarily before any subclass of Test
exists.
One thing hit me about your use case - that a particular Python environment
will only use one of these subclasses at a time. The ORM has less guesswork
to do if you in fact use the PolyTest class directly in queries, instead of
querying against the base Test. If it were me, I'd not bother with
"polymorphic" at all, and just set up a reference to the class that the app
needs:
class Test(...):
....
class PolyTest(...):
...
# fastcgi environment thing:
MyClass = PolyTest # (or PolyTest2, or PolyTest18, whatever your fastcgi thing
sets up)
Using the subclass directly has the advantage that you can directly refer to
those attributes that are specific to PolyTest in queries without switching
classes. Suppose Test has a column "x" and PolyTest has a column "y". The
with_polymorphic approach might have you doing this kind of thing:
query(Test).filter(PolyTest.y == 'value').filter(Test.x == 'value')
whereas if you just use PolyTest, or some alias, simpler:
query(MyClass).filter(MyClass.y == 'value').filter(MyClass.x == 'value')
Anyway, if you don't want to do that, then just set with_polymorphic after the
fact, which you can do using _set_with_polymorphic():
Test.__mapper__._set_with_polymorphic([PolyTest])
_set_with_polymorphic() was added in the middle of the 0.7 series to support
the ConcreteBase system, which has this same need, that is, to set up
with_polymorphic on the base class of a mapper hierarchy. You can also do it
via your declarative using __declare_last__():
class Test(...):
@classmethod
def __declare_last__(cls):
m = cls.__mapper__
# don't set it twice, if multiple mapper configs occur
if m.with_polymorphic:
return
m._set_with_polymorphic([PolyTest])
__declare_last__() is basically a class-level hook that's triggered by the
"after_configured" mapper event, which you could also use directly.
On Dec 7, 2012, at 7:56 PM, Gerald Thibault wrote:
> I have a test file (attached below) with a base class called Test, and an
> extended class called PolyTest, which is a polymorphic subclass of Test.
>
> I want to query for Test and get back a full PolyTest object. I do not want
> to use with_polymorphic: '*', as we have a large number of subclasses, only
> one of which will ever be used at a time (when the fastcgi environ is set,
> the subclass is assigned, and will not change for the life of the server).
> Each subclass is a globally used thing, so for client A, every instance of
> Test will always be TestA, which has that client's unique params. Using * on
> with_poly generated a monstrous query spanning every subtable we have, and is
> not an option.
>
> So, given that PolyTest inherits from Test (implying test needs to be mapped
> first), how do I pass the subclass PolyTest into the mapper_args of Test?
> There is not a single example on the entire site which provides guidance, as
> every single occurrence of with_polymorphic occurring within mapper args is
> using '*'. This makes me wonder if it is even possible, because I can't find
> a single example anywhere of someone passing classes into
> mapper_args['with_poly'].
>
> In the enclosed test, the final print should have a value attribute in it,
> which it does not.
>
> Also, using query.with_polymorphic is not a reasonable option here, as we
> have a huge platform which expects to query() and get back the exact result.
> We're not planning on replacing every instance of 'query()' in our codebase.
>
> --
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/sqlalchemy/-/l_78KhKtxogJ.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/sqlalchemy?hl=en.
> <with_poly_test.py>
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.