32

I was wondering if there is the equivalent of a "add all" or "bulk create" for many to many relationships which reduce the number of queries (I will be doing this for a long list)?

The docs on this subject seem to suggest that this is not possible:

https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/

**Associate the Article with a Publication:**
a1.publications.add(p1)

**Create another Article, and set it to appear in both Publications:**
a2 = Article(headline='NASA uses Python')
a2.save()
a2.publications.add(p1, p2)
a2.publications.add(p3)
snakesNbronies
  • 3,619
  • 9
  • 44
  • 73

4 Answers4

43

If you want to add queryset to bulk add or remove method of many to many relation models :

qs = Article.objects.all()
publications = Publications.objects.get(id=1)

publications.article_set.add(*qs)
publications.save()
publications.article_set.remove(*qs)
publications.save()
zzart
  • 11,207
  • 5
  • 52
  • 47
9

Of course it's possible! You just have to create an explicit intermediate table and then use this model's bulk_create method.

rantanplan
  • 7,283
  • 1
  • 24
  • 45
  • 25
    Actually, an explicit intermediate table isn't necessary, see http://stackoverflow.com/a/10116452/5112 – Tim Graham Oct 03 '12 at 17:39
  • @Tim I've forgotten about it. Good catch! – rantanplan Oct 03 '12 at 20:34
  • This is an extremely good idea if someone wishes to use the Postgresql COPY command (like [this app](https://github.com/california-civic-data-coalition/django-postgres-copy) does) instead of the django ORM for faster results with huge volumes of data. – raratiru Apr 12 '18 at 23:03
1

An example that adds a group and assign its permissions

group = Group.objects.create(name='user_manager')
codenames = ['delete_user', 'add_user', 'view_user', 'change_user']
permissions = Permission.objects.filter(codename__in=codenames)
group.permissions.add(*permissions)
ali orooji
  • 29
  • 2
0

You can just use RelatedManager.set for this:

a2 = Article(headline='NASA uses Python')
a2.save()
a2.publications.set([p1, p2, p3])

The documentation also tells us that there's no need to call .save() at the end.

ruohola
  • 21,987
  • 6
  • 62
  • 97