Django filter queryset by attribute subclass

1.6k Views Asked by At

I have a Slug model to identify Page objects. A BlogPost inherits from Page. I want to find a BlogPost given a Slug name, but no other Page objects.

EDIT: added models

class Slug(models.Model):
    name = models.CharField()
    page = models.ForeignKey('Page', null=True)

class Page(models.Model):
    slug = models.OneToOneField('Slug', related_name='primary_slug_set')
    content = models.TextField()

class BlogPost(Page):
    time = models.DateTimeField(auto_now_add=True, editable=False)

I think I'm after something like this:

Slug.objects.get(name=slug_name).filter(page=subclass_of(BlogPost))

I'm aware of the InheritanceManager and select_subclasses(BlogPost) but my query is for Slug, so I can't see that this helps unless I query Page and look for a BlogPost with my slug (is this a better way?).

Instead of filter I could iterate through all the slug results and manually check each one. It seems the way to do this is by checking if the Slug's page has any BlogPost attributes. At most there will be only a few slug conflicts to sift through and very rarely any at all.

Is there a way I can get the database query to do the filter for me?

2

There are 2 best solutions below

0
On

Haven't tested this but give it a try:

Slug.objects.filter(name=slug_name, blogpost__isnull=False)
0
On

If your Slug model defines the association with Pages in the following way:

class Slug(models.Model):
...
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    page = generic.GenericForeignKey('content_type', 'object_id')

Then, your query should look something like this:

content_type = ContentType.objects.get_for_model(BlogPost)
Slug.objects.filter(name=slug_name, content_type__pk=content_type.id)