Dalvtor
Dalvtor

Reputation: 3286

Django - Add the same set of objects to a queryset using a ManyToMany field

I have pizzas and I have toppings.

class Pizza(ModelBase):
    name = models.CharField(max_length=255)
    toppings = models.ManyToManyField('Topping', blank=True, related_name='pizzas')


class Topping(ModelBase):
    name = models.CharField(max_length=255)

Let's suppose I want to add the toppings Tomato and Cheese to every pizza in my database. At the moment I can do it with a nasty for loop:

toppings = Toppings.objects.filter(Q(name='Tomato') | Q(name='Cheese'))
for pizza in Pizza.objects.all():
    pizza.toppings.add(*toppings)

Is there a way to achieve the same thing without having to loop all the pizzas? Maybe using the through table that Django creates?

I know that I can delete the toppings from all the pizzas using the following query:

Pizza.toppings.through.objects.filter(topping__in=toppings).delete()

but I haven't been able to add toppings to multiple pizzas without the for loop.

Upvotes: 0

Views: 125

Answers (1)

iklinac
iklinac

Reputation: 15738

You could use .set() from reverse relation to set for each topping all pizzas as already mentioned in comment or you could do bulk_create through table entries

Something in a line of following:

topping_ids = Toppings.objects.filter(
     Q(name='Tomato') | Q(name='Cheese')
).values_list('id', flat=True)

pizza_ids= Pizza.objects.values_list('id', flat=True)

through_objects = [Pizza.toppings.through(topping_id=entry[0],
                   pizza_id=entry[1]) for entry in
                   itertools.product(topping_ids, pizza_ids)]


Pizza.toppings.through.objects.bulk_create(through_objects)

Upvotes: 2

Related Questions