Django查询集附加或注释相关对象字段

2024-04-10

需要附加到查询集结果相关的对象字段。

Models:

class User(models.Model):
    name = models.CharField(max_length=50)
    friends = models.ManyToManyField('self', through='Membership',
        blank=True, null=True, symmetrical=False)


class Membership(models.Model):
    status = models.CharField(choices=SOME_CHOICES, max_length=50)
    from_user = models.ForeignKey(User, related_name="member_from")
    to_user = models.ForeignKey(User, related_name="member_to")

我可以做这个:

>>> User.objects.all().values('name', 'member_from__status')
[{'member_from__status': u'accepted', 'name': 'Ann'}, {'member_from__status': u'thinking', 'name': 'John'}]

'member_from__status'包含我需要的信息。但除此之外,我还需要一个模型实例。

我想要的是:

>>> users_with_status = User.objects.all().do_something('member_from__status')
>>> users_with_status
[<User 1>, <User 2>]

>>> users_with_status[0] # <-- this is an object, so i can access to all its methods

查询集中的每个实例都有一个具有相应值的“member_from__status”字段:

>>> users_with_status[0].member_from__status
u'accepted'

如何实现这一目标?


您可以使用annotate https://docs.djangoproject.com/en/dev/topics/db/aggregation/#generating-aggregates-for-each-item-in-a-queryset and F https://docs.djangoproject.com/en/dev/ref/models/expressions/#f-expressions

>>> from django.db.models import F
>>> users = User.objects.all().annotate(member_from__status=F('member_from__status'))
>>> users[0].member_from__status
'accepted'

使用 Django 版本 1.11 和 2.2 进行测试


在回复评论时

我想我们对此相当感兴趣member_to__status than member_from__status(我们希望用户被请求接受友谊,而不是相反)

这是我的内容membership table:

status   |  from|   to
---------+------+-----
accepted |     1|    2
accepted |     2|    3
 refused |     3|    1

Since "不可能有对称的、递归的ManyToManyField https://stackoverflow.com/a/4135643/2116001(例如,用户 1 接受了用户 2,因此用户 1 现在位于用户 2 的好友列表中,但用户 2 也在用户 1 的好友列表中),这就是我检索所有实际好友的方式:

>>> for user in User.objects.all():
...     friends = user.friends.filter(member_to__status='accepted')
...     print(str(user.id) + ': ' + ','.join([str(friend.id) for friend in friends]))
1: 2
2: 3
3: 

如果你想拥有<User 1> in <User 2>的朋友,我建议再添加一个Membership当1到2的友谊被接受时。

这里我们假设一个Membership只能接受一次,因此最好添加独一无二 https://docs.djangoproject.com/en/dev/ref/models/options/#unique-together选项。尽管如此,如果我们有几个Membership与相同from_user,这就是发生的情况:

>>> # <Insert several Membership from one to another User>
>>> Membership.objects.filter(from_user__id=1, to_user__id=2).count()
3
>>> users = User.objects.annotate(member_from__id=F('member_from__id'))
>>> print('User Membership')
... for user in users:
...    print("%4d %10d" % (user.id, user.member_from__id))
User Membership
   1          1
   2          2
   1          3  # User 1 again
   1          4  # User 1 again
   3          None
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Django查询集附加或注释相关对象字段 的相关文章

随机推荐