В модели Django есть поле ManyToMany, как получить все ID, не перебирая объекты?

У меня есть структура данных следующего вида:

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)

А чтобы получить все идентификаторы начинок, относящихся к пицце, я могу сделать следующее:

list(map(lambda t: t.id, pizza.toppings.all()))

Но при этом из базы данных полностью извлекаются все топпинги, хотя мне нужны только идентификаторы. Есть ли способ получить идентификаторы без извлечения всех объектов (по соображениям производительности)?

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')))

Но, скорее всего, причиной возникновения проблем с производительностью была так называемая проблема N+1, когда вы сначала получаете записи для Pizza, а затем на каждую запись делаете дополнительный запрос для Topping объектов.

Используйте методы .values_list(), чтобы получить только идентификаторы в виде кортежей:

topping_ids = pizza.toppings.all().values_list("id")
# Example of result ( (4), (5), (12), (54) )
Вернуться на верх