【问题标题】:Django remove multiple m2m relations without loopDjango 无循环删除多个 m2m 关系
【发布时间】:2014-06-17 05:07:16
【问题描述】:

我试图找到从查询集中的许多对象中删除单个 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)

msgs 的所有Post 对象中,从not_seen_by 字段中删除配置文件prof 的最有效方法是什么?

最直接的方法是遍历所有对象:

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

【问题讨论】:

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


    【解决方案1】:

    我建议明确中间模型,然后直接使用它的管理器:

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

    【讨论】:

      【解决方案2】:

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

      这样

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

      如果我错了请告诉我..

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-17
        • 2015-08-22
        • 2011-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多