176

How would I delete an object from a Many-to-Many relationship without removing the actual object?

Example:

I have the models Moods and Interest.

Mood has a many-to-many field interests (which is a models.ManyToManyField(Interest)).

I create an instance of Moods called my_mood. In my_moods's interests field I have my_interest, meaning

>>> my_mood.interests.all()
[my_interest, ...]

How do I remove my_interest from my_mood without deleting either model instance? In other words, how do I remove the relationship without affecting the related models?

Daniel Holmes
  • 1,952
  • 2
  • 17
  • 28
Nachshon Schwartz
  • 15,289
  • 20
  • 59
  • 98

4 Answers4

287
my_mood.interests.remove(my_interest)

Django's Relations Docs

Note: you might have to get an instance of my_mood and my_interest using Django's QuerySet API before you can execute this code.

Cory Madden
  • 5,026
  • 24
  • 37
DrTyrsa
  • 31,014
  • 7
  • 86
  • 86
  • 8
    `AttributeError: 'RelatedManager' object has no attribute 'remove'` – Cerin May 02 '17 at 18:11
  • 2
    to add another `entry my_mood.interests.add(my_interest)` – Zohab Ali Aug 29 '18 at 08:18
  • @Cerin: (sorry for bumping an old comment) The question is about m2m, which implies a `ManyRelatedManager`, not a `RelatedManager`. That explains the `AttributeError`. – djvg Dec 14 '21 at 17:13
  • 3
    Note that [ManyRelatedManager.remove()](https://github.com/django/django/blob/stable/4.0.x/django/db/models/fields/related_descriptors.py#L964) also accepts object `id`s. – djvg Dec 14 '21 at 17:13
  • don't forget to call `my_mood.save()` – Prasen Mar 09 '22 at 06:17
  • You can remove a list or queryset like this: `my_mood.interests.remove(*interest_queryset)` – Viet Pm Mar 08 '23 at 10:32
124

If you need to remove all M2M references without touching the underlying objects, it's easier to work from the other direction:

interest.mood_set.clear()

While this does not directly address the OP's question, it's often useful in this situation.

shacker
  • 14,712
  • 8
  • 89
  • 89
  • 21
    Why was this downvoted? Granted it does not specifically address the OP's question, but I left the answer because it is of specific interest to people grappling with removing relations in M2M contexts, and removes the need to loop through instances. I thought it was a helpful related tip. – shacker Aug 16 '17 at 18:16
  • 3
    This was just useful to me (I was about to loop through and didn't want to). Thanks for posting it! – bwv549 Nov 09 '17 at 22:01
  • 1
    it could be better if you just add this point in above answer – brainLoop Oct 05 '18 at 13:13
  • 1
    Or with related name in models and `interest.relatedname.clear()` – Josh Aug 05 '19 at 08:33
23

In your case you can simply clear the relationship

my_mood.interests.clear()

Then perhaps when you are again creating new relation in your serializer you can do something like this

interests = Interests.objects.get_or_create(name='Something')
my_mood_obj.tags.add(tag[0])
my_mood_obj.save()
Sabyasachi
  • 1,484
  • 12
  • 20
-1

model.field.remove(object_you_want_to_remove)
In this case use: my_mood.interests.remove(my_interest)

Himaloy Mondal
  • 127
  • 2
  • 6