How to get only the base model instances from query?

Viewed 81

Hopefully my question won't have been asked before.

I've the following models in my Django app:

from django.db import models

class A(models.Model):
    some_attribute = models.SomeField()

    def some_method(self):
        do_stuff()
    
    # Note: not abstract

class B(A):
    def some_other_method(self):
        do_other_stuff()

Now, if I have one A and one B in the database, when I issue a A.objects.filter() call, I get the A and also the B instance (as expected).

But what if I in fact only want the instances of A specifically? I don't see how to write is as an .exclude() instruction. Could filtering with type == "A" be the intended way?

Follow-up: what if I have a class C inheriting from B, and so on, and want to exclude all instances of inheriting models?

1 Answers

You can filter with:

A.objects.filter(b=None)

to retrieve the A objects for which there is no B instance. This will make a LEFT OUTER JOIN on the B model, and thus only retain items where B is NULL.

Or you can omit all subclasses of A with:

data = {
    f.name: None
    for f in A._meta.get_fields()
    if f.one_to_one and A in f.related_model.__mro__
}
A.objects.filter(**data)
Related