首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在Django中创建引用两个相关模型的注释

如何在Django中创建引用两个相关模型的注释
EN

Stack Overflow用户
提问于 2019-06-13 07:04:59
回答 1查看 0关注 0票数 0

当一个相关对象上的字段值小于另一个相关对象上的字段值时,我正在尝试向QuerySet添加一个True / False的注释。

以下是一些示例的模型:

代码语言:javascript
复制
class RobotManager(models.Manager):
    queryset = super(RobotManager, self).get_queryset()
    queryset = queryset.annotate(canteen_empty=UNKNOWN CODE)
    return queryset

class Robot(models.Model):
    # Has some other unrelated stuff
    objects = RobotManager()

class CanteenLevel(models.Model):
    time = models.DateTimeField()
    robot = models.ForeignKey("SomeApp.Robot")
    gallons = models.IntegerField()

class RobotConfiguration(models.Model):
    time = models.DateTimeField()
    robot = models.ForeignKey("SomeApp.Robot")
    canteen_empty_level = models.IntegerField()

使用上述模型,随着机器人配置或CanteenLevel的变化,我们创建新记录并保存历史记录。

我想做的是向Robot QuerySet添加一个注释,指出Robot的食堂是否为空(Robot的最新CanteenLevel.gallons小于Robot的最新Configuration.canteen_empty_level)。

目的是使用QuerySet中的注释允许这样的语句:

代码语言:javascript
复制
bad_robots = Robot.objects.filter(canteen_empty=True)

我在注释中尝试过类似的东西:

代码语言:javascript
复制
canteen_empty=ExpressionWrapper(CanteenLevel.objects.filter(robot=OuterRef('pk')).order_by('-time').values('gallons')[:1] <= RobotConfiguration.objects.filter(robot=OuterRef('robot')).order_by('-time').values('canteen_empty_level')[:1], output_field=models.BooleanField))

但显然不允许使用“<=”运算符。

我也试过这个:

代码语言:javascript
复制
canteen_empty=Exists(CanteenLevel.objects.filter(robot=OuterRef('pk')).order_by('-time').values('gallons')[:1].filter(gallons__lte=Subquery(RobotConfiguration.objects.filter(robot=OuterRef('robot')).order_by('-time').values('canteen_empty_level')[:1]))))

但是在获取QuerySet片段后无法进行过滤。

任何帮助,将不胜感激!

EN

回答 1

Stack Overflow用户

发布于 2019-06-13 16:27:43

我们可以在这里做两个注释:

代码语言:javascript
复制
from django.db.models import Subquery, OuterRef

latest_gallons = Subquery(CanteenLevel.objects.filter(
    robot=OuterRef('pk')
).order_by('-time').values('gallons')[:1])

latest_canteen = Subquery(RobotConfiguration.objects.filter(
    robot=OuterRef('pk')
).order_by('-time').values('canteen_empty_level')[:1])

然后我们可以先Robot用这些注释对象,并过滤:

代码语言:javascript
复制
from django.db.models import F

Robot.objects.annotate(
    latest_gallons=latest_gallons,
    latest_canteen=latest_canteen
).filter(latest_gallons__lte=F('latest_canteen'))

这将构造一个如下所示的查询:

代码语言:javascript
复制
SELECT robot.*,
    (SELECT U0.gallons
     FROM canteenlevel U0
     WHERE U0.robot_id = robot.id
     ORDER BY U0.time DESC
     LIMIT 1) AS latest_gallons,
    (SELECT U0.canteen_empty_level
     FROM robotconfiguration U0
     WHERE U0.robot_id = robot.id
     ORDER BY U0.time DESC
     LIMIT 1) AS latest_canteen
FROM robot
WHERE
    (SELECT U0.gallons
     FROM canteenlevel U0
     WHERE U0.robot_id = robot.id
     ORDER BY U0.time DESC
     LIMIT 1
    ) <= (
     SELECT U0.canteen_empty_level
     FROM robotconfiguration U0
     WHERE U0.robot_id = robot.id
     ORDER BY U0.time DESC
     LIMIT 1
    )

但请注意,如果a Robot没有相关CanteenLevelRobotConfiguration(其中一个或两者),那么Robot它将不会包含在查询集中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100007015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档