Django model has ManyToMany field, how to get all IDs without fetching the objects?
I have a data structure like this:
class Pizza(models.Model):
name = models.CharField(max_length=100)
toppings = models.ManyToManyField(Topping, related_name="pizzas")
class Topping(models.Model):
name = models.CharField(max_length=100)
And to get all topping IDs related to a pizza I can do this:
list(map(lambda t: t.id, pizza.toppings.all()))
But this fetches all toppings completely from the database, even thought I only need the IDs. Is there a way to get the IDs without fetching the complete objects (for performance reasons)?
You can work with a Prefetch
object [Django-doc] that limits the columns fetched with .only(…)
[Django-doc]:
from django.db.models import Prefetch
Pizza.objects.prefetch_related(Prefetch('toppings', Topping.objects.only('id')))
But very likely the reason you got performance issues in the first place was the so-called N+1 problem where you first fetch the records for Pizza
, and then per record, you make an extra query for the Topping
objects.
Use .values_list() methods to get only the IDs as tuples:
topping_ids = pizza.toppings.all().values_list("id")
# Example of result ( (4), (5), (12), (54) )