Django无需循环删除多个m2m关系

时间:2014-04-30 18:32:00

标签: django django-models many-to-many

我正在尝试找到从查询集中的许多对象中删除单个m2m关系的最有效方法。例如,假设我有3个模型类来创建消息传递系统 - 配置文件,将多个配置文件链接在一起的线程,以及链接到单个线程的帖子,并跟踪哪些配置文件尚未读取帖子。

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')

给出个人资料:

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

一个帖子:

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

一个包含该帖子所有帖子的查询集:

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

prof中的所有not_seen_by个对象中的Post字段中删除个人资料msgs的最有效方法是什么?

最简单的方法是遍历所有对象:

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

但这似乎效率不高 - prof可能会也可能不会not_seen_by。能够在查询集本身上调用方法会更容易 - 像msgs.not_seen_by.remove(prof)这样的事情。有没有任何方法允许这样的事情?如果是这样,它甚至会更有效率,还是它本质上是运行循环的简写代码?

我已阅读this post,但使用Post.not_seen_by.through.objects仅允许通过idpostprofile进行过滤,因此我无法限制remove仅对Posts

链接的thrd进行操作

2 个答案:

答案 0 :(得分:2)

我建议将中间模型显式化,然后直接使用其管理器:

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()

答案 1 :(得分:1)

在我的视图中,您可以将删除限制为特定帖子的帖子

喜欢这个

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

请告诉我是不是错了..

如果这不起作用,您总是可以在Django中使用.raw编写原始查询。然后使用SQL的魔法来做到这一点。 :);)