Django:如何使用子查询注释 M2M 或 OneToMany 字段?

2023-11-24

I have Order物体和OrderOperation代表订单操作(创建、修改、取消)的对象。

从概念上讲,一个订单有一对多的订单操作。每次对订单进行操作时,都会在该操作中计算总计。这意味着当我需要查找订单的属性时,我只需使用子查询获取最后一个订单操作属性。

简化的代码

class OrderOperation(models.Model):
    order = models.ForeignKey(Order)
    total = DecimalField(max_digits=9, decimal_places=2)

class Order(models.Model)
    # ...

class OrderQuerySet(query.Queryset):

    @staticmethod
    def _last_oo(field):
        return Subquery(OrderOperation.objects
                        .filter(order_id=OuterRef("pk"))
                        .order_by('-id')
                        .values(field)
                        [:1])

    def annotated_total(self):
        return self.annotate(oo_total=self._last_oo('total'))

这样我就可以跑了my_order_total = Order.objects.annotated_total()[0].oo_total。效果很好。

问题

计算总计很容易,因为它是一个简单的值。但是,当存在M2M或OneToMany字段时,此方法不起作用。例如,使用上面的示例,让我们添加此字段:

class OrderOperation(models.Model):
    order = models.ForeignKey(Order)
    total = DecimalField(max_digits=9, decimal_places=2)
    ordered_articles = models.ManyToManyField(Article,through='orders.OrderedArticle')                                       

编写类似以下内容的代码不起作用,因为它仅返回 1 个外键(而不是所有 FK 的列表):

def annotated_ordered_articles(self):
    return self.annotate(oo_ordered_articles=self._last_oo('ordered_articles'))

目的

整个目的是允许用户在所有订单中搜索,在输入中提供列表或文章。例如:“请查找至少包含第 42 条或第 43 条的所有订单”,或“请查找恰好包含第 42 条和第 43 条的所有订单”等。

如果我能得到类似的东西:

>>> Order.objects.annotated_ordered_articles()[0].oo_ordered_articles
<ArticleQuerySet [<Article: Article42>, <Article: Article43>]>

or even:

>>> Order.objects.annotated_ordered_articles()[0].oo_ordered_articles
[42,43]

那可以解决我的问题。

我目前的想法

  • 也许像ArrayAgg(我正在使用 pgSQL)可以做到这一点,但我不确定在我的情况下如何使用它。
  • 也许这与values()该方法似乎无意处理文档中所述的 M2M 和 1TM 关系:

value() 和values_list() 都旨在作为优化 特定用例:检索数据子集,而无需开销 创建模型实例。这个比喻在处理问题时就站不住脚了 多对多和其他多值关系(例如一对多 反向外键的关系)因为“一行,一个对象” 假设不成立。


ArrayAgg如果您只想从所有文章中获取一个变量(即名称),那就太好了。如果您需要更多,有一个更好的选择:

prefetch_related

相反,您可以预取每个Order, 最新的OrderOperation作为一个整体的对象。这增加了轻松获取任何字段的能力OrderOperation没有额外的魔法。

唯一需要注意的是,当所选订单没有操作时,您将始终获得一个包含一项操作的列表或一个空列表。

为此,您应该使用prefetch_related查询集模型连同Prefetch object和自定义查询OrderOperation。例子:

from django.db.models import Max, F, Prefetch

last_order_operation_qs = OrderOperation.objects.annotate(
    lop_pk=Max('order__orderoperation__pk')
).filter(pk=F('lop_pk'))

orders = Order.objects.prefetch_related(
    Prefetch('orderoperation_set', queryset=last_order_operation_qs, to_attr='last_operation')
)

然后你就可以使用order.last_operation[0].ordered_articles获取特定订单的所有已订购物品。你可以加prefetch_related('ordered_articles')首先查询集可以提高性能并减少对数据库的查询。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Django:如何使用子查询注释 M2M 或 OneToMany 字段? 的相关文章

随机推荐

  • AutoFixture IEnumerable 与 CreateMany() 的行为

    看帖子的时候here 看起来我应该能够使用创建多个对象CreateMany 使用迭代它们foreach 然后将它们作为数组返回 我看到的是 每次迭代似乎每次都会创建新对象 这是预期的行为吗 要创建的实体 public class TestE
  • 如何使用 Dart 从不同的 URL 提供静态文件?

    有了 Dart 我就得到了awesome html 但我希望它是 awesome 这纯粹是一个 htaccess 我正在使用 Apache 或者有没有办法通过 Dart 或 现代 Web 开发 方式来解决这个问题 This htaccess
  • 将链接插入 MatSnackBar

    是否可以在 Angular Material 2 中插入链接MatSnackBarModule 我尝试在文本中执行此操作 但它将 html 显示为文本 const text a login a this snackBar open text
  • Google adsense 响应服务器响应状态为 400 ()

    我第一次在我的网站上实施 google adsensemyPleaks 在这里我面临下面提到的错误 Failed to load resource the server responded with a status of 400 谁能帮我
  • OpenCV:如何在图像上应用彩虹渐变图?

    假设我们有一个通过 openCV 以某种方式修改的图像 现在我们很乐意申请它渐变贴图 就像我们可以通过 Photoshop 应用的那样 所以我想知道如何通过 openCV 应用渐变图 彩虹色 这是一种使用 Python 创建假 伪彩色图像的
  • 从文本区域执行 javascript

    我不完全确定这是否可能 但我正在尝试在浏览器中创建一个在页面上运行 javascript 的迷你人造编辑器 这就是我理论上一直在尝试做的事情 HTML
  • 使用 Protractor 从 chromedriver 获取 HTTP 请求(性能日志)

    我正在使用量角器进行 Angular 的 e2e 测试 并且我正在拼命地尝试获取带有标头和正文的 HTTP 请求日志 我已经像这样配置了量角器 useAllAngular2AppRoots true ignoreUncaughtExcept
  • 在 NSString 中将 NSData 显示为二进制

    我在资源文件夹中有一个二进制文件 file bin 我想读取它并将其显示为二进制文件 这个想法是将二进制信息放入数组中 但是首先 我尝试在 UILabel 中显示它 如下所示 NSData databuffer NSString 字符串数据
  • XQuery 多个xml 文件?

    是否可以从 xQuery 打开 2 个文档并对它们进行联接 是的 这里是一个例子来自XQuery 规范 连接将来自多个源的数据组合成一个结果 是一种非常重要的查询类型 在本节中 我们将说明如何在 XQuery 中表达几种类型的连接 我们的示
  • Xbox One 开发模式和 Unity 免费版本 [已关闭]

    Closed 这个问题是与编程或软件开发无关 目前不接受答案 我有一台零售 Xbox One 主机 并激活了开发模式 Unity 最新免费版本 和一个 MSDN 个人开发者帐户 我能够在 Xbox 上从 Visual Studio 部署测试
  • 在 ActionScript 3 中嵌入 mp3 不起作用

    我在使用 actionscript 3 时遇到问题 尤其是在使用嵌入标签时 我有这个代码 Embed source sound mp3 private static var soundClip Class var sound Sound n
  • 指定相对路径

    我有一个 Windows 窗体项目 在当前目录中 我有一个包含 chm 文件的帮助文件夹 从应用程序启动它们的最简单方法是什么 我如何指定它们的相对路径 The 环境 当前目录属性将设置为 exe 文件的位置 因此 如果您将帮助文件夹放在那
  • Workmanager 在 Android 12 Android kotlin 中无法处理延迟

    嘿 我正在 kotlin 中工作 WorkManager 我不明白一些代码并给我带来了这个错误 有人能更详细地向我解释一下吗 2022 01 06 16 48 33 501 14483 14483 com example app E And
  • 用MySQL计算中位数的简单方法

    使用 MySQL 计算中位数的最简单 希望不会太慢 的方法是什么 我用过AVG x 寻找平均值 但我很难找到计算中位数的简单方法 现在 我将所有行返回给 PHP 进行排序 然后选择中间行 但肯定有一些简单的方法可以在单个 MySQL 查询中
  • 如何设置 Apache ProxyPass 以保留 Express 路由

    在我的 Apache 配置中 我转发所有流量 node到港口3000 Express 服务器正在侦听
  • 如何在 Bash 中转义单引号字符串中的单引号?

    我想在 Bash 中显示一个字符串 如下所示 I m a student 当然你可以这样做 echo I m a student 但是如何在字符串周围使用单引号来实现这一点呢 echo I m a student 不起作用 但以下有效 ec
  • DoCmd.DeleteObject acTable 与 DoCmd.DeleteObject acTable 之间有什么区别?掉落表

    Details 我有一个 MS Access 数据库过程 可以在数据库中本地创建表 但是 我想确保我创建的表经过测试 如果测试失败 我需要删除 删除已创建的其他表 我猜基本上是一个回滚过程 问题 我遇到了两种删除表的方法 但无法弄清楚其中一
  • android中从包名获取应用程序名称

    我正在尝试开发一个android应用程序 它可以列出所有具有缓存的应用程序 我成功地获取了有关缓存的信息 但现在我想在屏幕上显示那些具有缓存的应用程序 我有包名称 但是问题是如何从包名称中获取应用程序名称 假设包名称是com android
  • 如何将字典中的值添加到电子表格?

    我有一个模板电子表格文档 其中有两列 服务器名称和 IP 地址 如何填充电子表格 以便每个字典键位于 服务器 列中自己的单元格中 而相应的值位于 IP 列中它旁边的单元格中 我正在使用 EPPlus 库 但找不到有关该主题的任何内容 以下是
  • Django:如何使用子查询注释 M2M 或 OneToMany 字段?

    I have Order物体和OrderOperation代表订单操作 创建 修改 取消 的对象 从概念上讲 一个订单有一对多的订单操作 每次对订单进行操作时 都会在该操作中计算总计 这意味着当我需要查找订单的属性时 我只需使用子查询获取最