In Django, when you have a parent class and multiple child classes that inherit from it you would normally access a child through parentclass.childclass1_set or parentclass.childclass2_set, but what if I don't know the name of the specific child class I want?
Is there a way to get the related objects in the parent->child direction without knowing the child class name?
You can use django-polymorphic for that.
It allows to automatically cast derived classes back to their actual type. It also provides Django admin support, more efficient SQL query handling, and proxy model, inlines and formset support.
The basic principle seems to be reinvented many times (including Wagtail's
.specific
, or the examples outlined in this post). It takes more effort however, to make sure it doesn't result in an N-query issue, or integrate nicely with the admin, formsets/inlines or third party apps.In Python, given a ("new-style") class X, you can get its (direct) subclasses with
X.__subclasses__()
, which returns a list of class objects. (If you want "further descendants", you'll also have to call__subclasses__
on each of the direct subclasses, etc etc -- if you need help on how to do that effectively in Python, just ask!).Once you have somehow identified a child class of interest (maybe all of them, if you want instances of all child subclasses, etc),
getattr(parentclass,'%s_set' % childclass.__name__)
should help (if the child class's name is'foo'
, this is just like accessingparentclass.foo_set
-- no more, no less). Again, if you need clarification or examples, please ask!Here's my solution, again it uses
_meta
so isn't guaranteed to be stable.It turns out that what I really needed was this:
Model inheritance with content type and inheritance-aware manager
That has worked perfectly for me. Thanks to everyone else, though. I learned a lot just reading your answers!
You can achieve this looking for all the fields in the parent that are an instance of django.db.models.fields.related.RelatedManager. From your example it seems that the child classes you are talking about are not subclasses. Right?
An alternative approach using proxies can be found in this blog post. Like the other solutions, it has its benefits and liabilities, which are very well put in the end of the post.