Frage

I am trying to find the most efficient way to remove a single m2m relation from many objects in a queryset. For example, lets say I have 3 model classes to create a messaging system - profiles, threads that link multiple profiles together, and posts that are linked to a single thread and keep track of which profiles have not read the post yet.

class Profile(models.Model):
   # stuff here

class Thread(models.Model):
   profiles = models.ManyToManyField('Profile')

class Post(models.Model):
   thread = models.ForeignKey('Thread')
   not_seen_by = models.ManyToManyField('Profile')

Given a profile:

prof = Profile.objects.get(id=profile_id)

A thread:

thrd = Thread.objects.get(id=thread_id)

And a queryset with all the posts to the thread:

msgs = Post.objects.filter(thread=thrd)

What is the most efficient way to remove the profile prof from the field not_seen_by in all Post objects in msgs?

The most straightforward way to do it would be to loop through all the objects:

for m in msgs:
    m.not_seen_by.remove(prof)

But this doesn't seem very efficient - prof may or may not be in not_seen_by. It would be much easier to be able to call a method on the queryset itself - somethings like msgs.not_seen_by.remove(prof). Is there any method that allows for anything like this? If so, would it even be more efficient, or would it essentially be shorthand code for running the loop?

I have read this post, but using Post.not_seen_by.through.objects only allows filters through id, post, and profile, so I wont be able to limit the remove operation to only those Posts that are linked to thread thrd

War es hilfreich?

Lösung 2

In my View you can Limit The deletion to Posts of a specific thread.

Like this

Post.not_seen_by.through.objects.filter(post__thread=t, profile=prof).delete()

Please tell if I am wrong..

If this Doesn't work than you can always write Raw Queries using .raw in Django. Then use SQL's magic to do this. :) ;)

Andere Tipps

I suggest making the intermediate model explicit, and then using its manager directly:

class Profile(models.Model): 
    # stuff here

class Thread(models.Model): 
    profiles = models.ManyToManyField('Profile') 

class Post(models.Model): 
    thread = models.ForeignKey('Thread') 
    not_seen_by = models.ManyToManyField('Profile', through='NotSeenBy')

class NotSeenBy(models.Model):
    post = models.ForeignKey('Post')
    profile = models.ForeignKey('Profile')

prof = Profile.objects.get(id=profile_id)
thrd = Thread.objects.get(id=thread_id)
NotSeenBy.objects.filter(post__thread=thrd, profile=prof).delete()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top