pythondjangodjango-polymorphic

Filtering plain models on their relation to a subclass of a django polymorphic model?


I have a plain Django model that has a ForeignKey relation to a django-polymorphic model.

Let's call the first PlainModel that has a content ForeignKey field to a polymorphic Content model with subtypes Video and Audio (simplified example).

Now I want to query for all PlainModel instances that refer to a Video.

Problem is all the docs I find are about filtering directly via the polymorphic model itself. So in this example something like Content.objects.instance_of(Video). But I need PlainModel's, so it would need to look something like PlainModel.objects.filter(content__instance_of=Video). I tried a bunch of variations but I cannot find anything that works.

In the docs they use Q(instance_of=ModelB), but this doesn't work on the relation as Q(content__instance_of=ModelB). It gives an error like 'Cannot query "x": Must be "y" instance.' even with the translation call, I guess because the PlainModel is not polymorphic aware.

I have a temporary hack that directly filters on the polymorphic_ctype field using regular django filter like PlainModel.objects.filter(content__polymorphic_ctype_id=my_content_type_id), but this doesn't handle subclasses. Eg: ExtendedVideo would not be found when looking for Video, because it would have a different ContentType id.

I could go solve this and keep a list of allowed subtypes or parse the type hierarchy to get more content types for the filter but that seems to duplicating functionality from django-polymorphic.


Solution

  • You can do this by first getting all the PlainModel instances that have a Video subtype, and then querying for the foreign key relationships that are in that queryset:

    content_videos = Content.objects.instance_of(Video)
    plain_model_videos = PlainModel.objects.filter(content__in=content_videos)
    

    Please see the docs for reference.