4

I have the following problem: I need to update a set of objects with the same many_to_many field. So lets say I have the following models

class Blog:
    name = CharField
    users = M2M(User)

class User:
    name = CharField

And now trying something like users = Users.objects.filter(**somefilters) and Blog.objects.filter(#getting very large list of blogs).update(users=users)

Actually the update operation does not work, as M2M objects don't seem to be supported. And if I am trying to do something list

for blog in large_list_of_blogs:
    blog.users.add(users)

It's very very slow, as every object is accessed individually.

Oleg Tarasenko
  • 9,324
  • 18
  • 73
  • 102

1 Answers1

2

What you can do is to use bulk_create on the intermediate model of the M2M relation.

What I can see from you example is that you want to assign the same set of users for a group of blogs.

So an example implementation would look like:

users = Users.objects.filter(**somefilters)
blogs = Blog.objects.filter(**another_filters)

BlogUserRelation = Blog.users.through

relations = []
for blog in blogs:
    relations.extend([BlogUserRelation(
                        user_id=user.id,
                        blog_id=blog.id
                    ) for user in users])

BlogUserRelation.objects.bulk_create(relations)

This is efficient in terms of db queries, but will need to load all the objects into memory. In order to make it memory efficient you need to use some kind of queryset iterator and traverse the blog objects on chunks.

One more thing to have in mind, usually when you use blog.users.add(users), django checks for existing user-blog relations and exclude them, with bulk_create this is not the case and you will have to do it manually if you need.

Community
  • 1
  • 1
Todor
  • 15,307
  • 5
  • 55
  • 62