B.Adler
B.Adler

Reputation: 1549

How can I remove an object from a many to many for a queryset without iteration?

In Django, I have a many to many relationship between two models.

I want to remove an instance of model_one from several instances of model_two.

I have:

user = User.objects.get(id=user_id)
conversations = Conversation.objects.filter(users=user)
for conversation in conversations.iterator():
    conversation.users.remove(user)

This needs to evaluate every single instance of Conversation. Is there a way to do this without iteration?

UPDATE:

Added the models to add clarity to the question.

class User(EditMixin):
    conversations = models.ManyToManyField('Conversation', related_name='users')
    name = models.CharField(max_length=255, blank=True, null=True)
    permalink = models.URLField(blank=True, max_length=2083)
    rating = models.DecimalField(decimal_places=2, max_digits=4, blank=True, default=0)
    remote_id = models.CharField(max_length=4096, blank=True, null=True)
    summary = models.CharField(max_length=255, blank=True, null=True)

    objects = UserManager()

class Meta:
    verbose_name_plural = 'Users'


class Conversation(EditMixin, BasicInfoMixin):
    content = models.TextField(blank=True, null=True)
    update_enabled = models.BooleanField(default=False)

    objects = ConversationManager()

class Meta:
    verbose_name_plural = 'Conversations'

UPDATE 2:

I think my question is unclear. The clear() method removes all items in a m2m field. What I would like to do is the following:

I have a queryset of User objects. Each has a m2m field with conversations. Every item in the queryset has conversation 7 in the m2m field, but also contains other conversations. I want to only remove conversation 7 from the m2m of every object in the queryset, while maintaining the other conversations. All of this, without iteration if possible, e.g.

before:

Jeremy.conversations: [1, 2, 3, 4, 7]

Tiffany.conversations: [3, 7, 9]

Jeff.conversations: [5, 6, 7]

after:

Jeremy.conversations: [1, 2, 3, 4]

Tiffany.conversations: [3, 9]

Jeff.conversations: [5, 6]

Upvotes: 5

Views: 5579

Answers (1)

iklinac
iklinac

Reputation: 15758

You could use something like this

user = User.objects.get(id=user_id)
user.conversation_set.clear()

if it from other end on many to many (applicable to your solution after edit )

user.conversations.clear()

You could then have multiple elements as args in remove

user.conversations.remove(*conversations)

or use .through to access pivot table and delete from it

Upvotes: 4

Related Questions