Let's say I have a database with Movies, Books, and Software, and they all inherit a single Item model.
class Item(models.Model):
...
class Movie(models.Model):
item = models.OneToOneField(Item)
...
class Book(models.Model):
item = models.OneToOneField(Item)
...
class Software(models.Model):
item = models.OneToOneField(Item)
...
Now I want to make a database query on Item but I want to pick up the related object to that item, whether it be a Movie, Book, or Software. If all the items were one type, say, Movies, then I could do the following:
Item.objects.prefetch_related('movie')
However, I need to be able to fetch the related object no matter what type it is. Can I run:
Item.objects.prefetch_related('movie', 'book', 'software')
Will this find the related object no matter what type it is, and will this be efficient? Is there a better way of doing this?
I'll suppose the OneToOneField
s have related_name
set as your QuerySet examples indicate, that is, 'movie'
, 'book'
and 'software'
respectively.
To traverse a one-to-one relationship backwards you don't need prefetch_related
, this is something that is easy to achieve with a LEFT OUTER JOIN
automatically generated by select_related
. That means, you should be able to do
Item.objects.select_related('movie', 'book', 'software')
and each returned Item instance will automatically contain a cached instance of the corresponding Movie
, Book
and Software
(if there is one, of course).
prefetch_related
is only needed when you want to avoid an O(N) query issue with many-to-many or many-to-one relationships, that is, with a ManyToManyField
or a reverse traversal of ForeignKey
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With