【问题标题】:Django ManyToMany filtering by set size or member in the setDjango ManyToMany按集合大小或集合中的成员过滤
【发布时间】:2012-12-28 09:26:34
【问题描述】:

我正在使用django 来维护一个消息数据库。
其中,我有以下 模型

class User(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=10)

class Message(models.Model):
    id = models.IntegerField(primary_key=True)
    body = models.CharField(max_length=200)
    users = models.ManyToManyField(User)

我正在尝试编写一个实用方法,该方法为给定用户提供与他(和他一个人)相关联的消息。

即为:

m1 = Message(id=1, body='Some body')
m1.save()
m2 = Message(id=2, body='Another body')
m2.save()
m3 = Message(id=3, body='And yet another body')
m3.save()

u1 = User(name='Jesse James')
u1.save()
u2 = User(name='John Doe')
u2.save()

m1.users.add(u1, u2)
m2.users.add(u1)
m3.users.add(u2)

getMessagesFor('Jesse James')

只会返回m2
假设我在user 中有正确的模型实例,它归结为一行,我尝试了以下这些:

    user.message_set.annotate(usr_cnt=Count('users')).filter(usr_cnt__lte=1)

或者:

    messages = Message.objects.filter(users__id__in=[user.id])

还有:

    messages = Message.objects.filter(users__id__exact=user.id)

还有:

    messages = Message.objects.filter(users__contains=user)

等等...我总是同时得到m2 AND m1
尝试了注释、排除、过滤器等。

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 请检查我的答案,它应该可以满足您的需求

标签: python django django-models django-queryset


【解决方案1】:
qs = Message.objects.annotate(cc=Count('users')).filter(cc=1)

上面的查询将返回所有只有一个用户与之关联的消息。

要按用户过滤,请在末尾添加另一个过滤器以根据用户过滤带注释的查询:

qs = Message.objects.annotate(cc=Count('users')).filter(cc=1).filter(users__id=user.id)
# if user user.id=1, this will return only m2

【讨论】:

  • 谢谢,这成功了,但我不明白为什么双重过滤会做一个单一的(更直观的)过滤器没有做的事情。我的第一条评论是关于最初的答案,同时您对其进行了编辑。
【解决方案2】:

可能是这样的? (未测试)

for msg in Messages.objects.all():
    if (user in msg.users_set.all() and len(msg.users_set.all()) == 1):
        # do something

【讨论】:

    猜你喜欢
    • 2014-04-18
    • 1970-01-01
    • 1970-01-01
    • 2013-03-27
    • 1970-01-01
    • 1970-01-01
    • 2016-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多