我有一个类似于此的数据库模式:
class User(models.Model):
… (Some fields irrelevant for this query)
class UserNotifiy(models.Model):
user = models.ForeignKey(User)
target = models.ForeignKey(<Some other Model>)
notification_level = models.SmallPositivIntegerField(choices=(1,2,3))
现在,我想查询具有特定目标的UserNotify对象且至少具有特定通知级别(例如2)的所有用户。
如果我这样做:
User.objects.filter(usernotify__target=desired_target,
usernotify__notification_level__gte=2)
我获得具有指定目标的UserNotify对象的所有用户以及至少一个带有notification_level大于或等于2的UserNotify对象。但是,这两个UserNotify对象不必相同。
我知道我可以这样做:
user_ids = UserNotify.objects.filter(target=desired_target,
notification_level__gte=2).values_list('user_id', flat=True)
users = User.objects.filter(id__in=user_ids).distinct()
但这似乎对我来说太过分了,我相信它会执行两个查询。
有没有办法用单个查询解决我的问题?
答案 0 :(得分:0)
我不确定我是否理解你的问题,但是:
class User(models.Model):
… (Some fields irrelevant for this query)
class UserNotifiy(models.Model):
user = models.ForeignKey(User, related_name="notifications")
target = models.ForeignKey(<Some other Model>)
notification_level = models.SmallPositivIntegerField(choices=(1,2,3))
然后
users = User.objects.select_related('notifications').filter(notifications__target=desired_target,
notifications__notification_level__gte=2).distinct('id')
for user in users:
notifications = [x for x in user.notifications.all()]
我现在没有方便使用我的流浪盒,但我相信这应该有效。
答案 1 :(得分:0)
我一直在寻找这种行为,但我从来没有找到比你描述的更好的方法(为用户ID创建查询并将其注入用户查询)。请注意,这并不错,因为如果您的数据库支持子查询,您的代码应该只触发由查询和子查询组成的一个请求。
但是,如果您只需要User对象中的特定字段(例如first_name),则可以尝试
qs = (UserNotify.objects
.filter(target=desired_target, notification_level__gte=2)
.values_list('user_id', 'user__first_name')
.order_by('user_id')
.distinct('user_id')
)
答案 2 :(得分:0)
实际上,我不知道如何运行第一个查询,因为usernotify
不是User
的有效字段名称。
你应该像在第二个例子中那样从UserNotify
开始:
UserNotify.objects.filter(
target=desired_target,
notification_level__gte=2
).select_related('user').values('user').distinct()