在Django中连接查询

0 投票
2 回答
670 浏览
提问于 2025-04-15 15:24

我有一个查询,可以从我的头像应用中获取32个头像图片:

newUserAv = Avatar.objects.filter(valid=True)[:32]

我想把这个查询和django的用户模型结合起来,这样我就能得到最近加入的32个有头像的人,并按加入日期排序。

有什么好的方法可以把这两个查询连接起来吗?

这个头像应用是一个可重用的应用,它的模型是:

image = models.ImageField(upload_to="avatars/%Y/%b/%d", storage=storage)
user = models.ForeignKey(User)
date = models.DateTimeField(auto_now_add=True)
valid = models.BooleanField()

需要注意的是,日期字段是头像更新的日期,所以不适合我的需求。

2 个回答

0

你不能把两个不同的基础模型的查询结果合在一起。Django 不允许这样做,如果你试图这么做,它会报错告诉你不能这样。

不过,如果一个模型里有指向另一个模型的外键,那么在你的查询中加上 select_related(),就可以在一次数据库查询中把相关的对象一起取出来,这样你就可以直接使用这些对象,而不用再去数据库查了。

2

你可以在自己的用户类里加一个字段,表示这个用户有头像。这样你就可以很方便地查询了。你可能需要继承用户类或者和 django.contrib.auth.models.User 组合使用。

或者你可以这样做:

from django.utils.itercompat import groupby
avatars = Avatar.objects.select_related("user").filter(valid=True).order_by("-user__date_joined")[:32]
grouped_users = groupby(avatars, lambda x: x.user)
user_list = []
for user, avatar_list in grouped_users:
    user.avatar = list(avatar_list)[0]
    user_list.append(user)
# user_list is now what you asked for in the first_place: 
# a list of users with their avatars

这里假设每个用户只有一个头像。如果你的模型允许每个用户有多个头像,那你就得注意不要存储超过一个头像。

代码片段的解释: 这个代码请求了最近加入的32个用户的头像,并且把相关的用户信息一起请求过来,这样在后面的代码中就不需要再查询数据库了。 头像列表会根据用户进行分组,list 会从生成器 avatar_list 中获取所有项,并把第一个项(应该只有一个)赋值给 user.avatar

需要注意的是,这一步不是必须的,你也可以这样做:

for avatar in avatars:
    user = avatar.user

不过通过 user.avatar 来访问头像可能会更自然一些。

撰写回答