35

Django's ManyToMany field can be populated using my_field.add(my_instance), but as I understand it only my_instance.id is actually needed to perform the corresponding SQL query.

If I want to add an object by its id, I can use my_field.add(MyModel.objects.get(id=id)), but this will generate two queries instead of one. How can I avoid this extra query?

pintoch
  • 2,293
  • 1
  • 18
  • 26

1 Answers1

51

Although the documentation of the add method does not mention it, you can actually pass directly an id to it, like this:

my_instance.add(id)

Surely, this only works when the primary key is used as the identifier for the relation (the default behaviour).

pintoch
  • 2,293
  • 1
  • 18
  • 26
  • 3
    Passing the id directly results in a TypeError for me (Django 1.10.5): "TypeError: 'MyRelatedModel' instance expected, got '5835da11-dcde-47da-9664-e5c13e235ccc'" – Oskar Persson Jan 19 '17 at 11:51
  • 1
    in 2.2 docs now mention this: "add() also accepts the field the relation points to as an argument. The above example can be rewritten as b.entry_set.add(234).' – Tim Tisdall Oct 17 '19 at 17:44
  • hmm.. it seems using an id works slightly differently. If the relation already exists then it throws an `IntegrityError` where adding the object just ignores the existing relation. – Tim Tisdall Oct 17 '19 at 17:57
  • 2
    So, I'm not quite right.... You need to make sure the pk is of the same type that's expected or you get `IntegrityError`. For example, if you do `.add('3')` and the id should be an integer you will get an error if the relation already exists. If you do `.add(3)` then it will ignore the duplicate. – Tim Tisdall Oct 17 '19 at 18:04