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