I currently have a model with 2 m2m fields like this:
class Person:
stuff = models.CharField(max_length=50)
products = models.ManyToManyField(Product)
books = models.ManyToManyField(Book)
How can I query this model to get both products and books in the same query?
I can do something like this:
selected_person = Person.objects.get(pk=1)
selected_person_products = selected_person.products.all()
selected_person_books = selected_person.books.all()
If I understand correctly this would make 3 separate queries to the DB, is there a better way?
Not with trying to retrieve this data as objects there isn’t.
(Nor, in the general case, would I be worried about it. If you’re dealing with data of sufficient size such that this makes a material difference, I’d be looking for more fundamental architectural changes.)
You could, in theory, create a query with subqueries to retrieve this related data as values stored in annotated fields, but if you’re looking to work with the Product
and Book
instances as objects, you’re going to end up creating those objects yourself anyway.
Side Note: You could also reduce this from three queries to two by reversing your perspective on the queries:
sp_products = Product.object.filter(person_id=1).select_related('person')
sp_books = Book.object.filter(person_id=1).select_related('person')
You can then access the Person object from any instance of either sp_products or sp_books. However, this will not return any Person
not related to any Product
or Book
, so it may not be adequate for your requirement.