83

In one model, I have this:

class MyModel(models.Model):
    relations = models.ManyToManyField(OtherModel)
    ....

and if I choose:

my_object.relations.remove(other_model_object)

it works.

How to remove all objects from the relations? my_object.relations.clean() is not working.

Hasta Dhana
  • 4,699
  • 7
  • 17
  • 26
Nips
  • 13,162
  • 23
  • 65
  • 103
  • 7
    .remove() and .clear() will remove the relationships, but they won't actually delete related objects...is that what you're trying to do? – Brandon Taylor Aug 29 '11 at 13:14
  • see here http://stackoverflow.com/questions/4719137/how-do-i-remove-multiple-objects-in-a-manytomany-relationship-based-on-a-filter – madjardi Feb 05 '15 at 13:34

5 Answers5

88

First, you'll need to clear the relationship(s) by using .clear() or .remove(), whichever suits your needs better according to the docs.

After that, you'll need to delete the object(s) by using the [YourModel].delete() method.

solarissmoke
  • 30,039
  • 14
  • 71
  • 73
Brandon Taylor
  • 33,823
  • 15
  • 104
  • 144
  • for m2m fields `.remove()` will delete the relationship using `QuerySet.delete()`. This should delete the related object I suppose. Correct me if I am wrong. – sgauri Mar 13 '18 at 12:19
  • 3
    @sgauri I don't feel 100% confident, but the behavior I observe is that, when calling `remove`, only the "through" record is deleted, and `other_model_object` is not deleted. I don't think the documentation for `remove` says specifically whether or not `other_model_object` is deleted, like it does for `clear`. – David Winiecki Feb 05 '19 at 22:30
50

If you need to delete only the relationship for all instance between 2 models then you can do that by accessing the Manager of the relationship table. The m2m relationship table can be accessed via MyModel.relations.through so for deleting the relationships it becomes easy:

MyModel.relations.through.objects.all().delete()

reference:

https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ManyToManyField.through

Rachid
  • 2,463
  • 1
  • 21
  • 9
  • 36
    Be careful with this as this will delete all rows in the m2m table as calling through.objects decouple the m2m from MyModel. So you need to do something like `Author.books.through.objects.filter(author_id=author.pk).delete()` – Christoffer Nov 15 '13 at 14:59
  • this was what I was looking for. useful, but not the correct answer. – benzkji Nov 09 '16 at 20:59
  • Warning! This is really dangerous function as it will delete the entire relationship table! – Hieu Nguyen Nov 01 '17 at 16:58
24

Use my_object.relations.clear()

camara90100
  • 852
  • 2
  • 10
  • 18
5

models.py

# consider Author & Book model
class Author(models.Model):
    name = models.CharField(max_length=200)

class Book(models.Model):
    authors = models.ManyToManyField(Author, related_name='books')
    title   = models.CharField(max_length=200)
    desc    = models.TextField()

Here, we assume that a book have many author & a authors have many book.

book (M) <------> (M) author

  1. now, we find a book all authors & some operations
books = Book.objects.all()
if len(books) > 0:
    book = books[0]

    # first book all authors
    first_book_all_authors = book.authors.all()
    
    # clear/remove all authors | (not same as delete)
    book.authors.clear()
    
    # add a author
    new_author = Author.objects.create(name = "Author name: Jhon smith")
    book.authors.add(new_author)

    # add multiple author
    all_authors = Author.objects.all()
    book.authors.set(all_authors)

    # remove a author
    auth1 = Author.objects.filter(pk = 1).first()
    book.authors.remove(auth1) # if auth1 is not None, then it's remove this author
  1. now, you find a author all books & some operations
authors = Author.objects.all()
if len(authors) > 0:
    auth = authors[0]

    # first author all book
    first_author_all_books1 = auth.books.all()   # if set related field name | related_name='books'
    first_author_all_books2 = auth.book_set.all() # if not set related field name | 'modelName'_set.all()
    
    # clear/remove all books | (not same as delete)
    auth.books.clear()
    
    # add a book
    new_book = Book.objects.create(title = "new book", desc="book desc")
    auth.books.add(new_book)

    # add multiple book
    all_books = Book.objects.all()
    auth.books.set(all_books)

    # remove a book
    book = Author.objects.filter(pk = 1).first()
    auth.books.remove(book) # if book is not None, then it's remove this book
    

NB: THINK SIMPLY

iamdipta
  • 346
  • 3
  • 7
4

To remove all related objects without deleting them, just use:

my_object.relations.remove(*my_object.relations.all())
Daniel Holmes
  • 1,952
  • 2
  • 17
  • 28