You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中无需for循环获取指定客户订购产品列表的方法

问题说明

我是Django和SQL的初学者,目前正尝试通过解决简单问题入门相关技术。我定义了Client(客户)、Product(产品)、Order(订单)3个模型,想要实现列出指定客户所订购全部产品的需求,模型定义如下:

class Client(models.Model):
    name = models.CharField(max_length=32)
    .....

class Product(models.Model):
    product_name = models.CharField(max_length=32)
    .....

class Order(models.Model):
    client = models.ForeignKey(Client,on_delete=models.CASCADE)
    product = models.ForeignKey(Product,on_delete=models.CASCADE)
    .....

我当前的实现代码如下:

client= Client.objects.get(id=1) # 目标客户
orders = client.order_set.all()
# 另一种等价写法 orders = Order.objects.filter(client=client)
list_of_orders=[order.product for order in orders] 

想确认是否存在更优的Django原生特性实现方案,不需要手写for循环就能获取目标产品列表。

实现方案

完全可以用Django ORM原生的跨关联查询实现,不需要手写循环,性能比当前写法更好,还能避免常见的N+1查询问题。
最简洁的写法是直接查询Product表,通过关联路径过滤出对应客户的订单关联的产品:

client = Client.objects.get(id=1)
# 自动完成表关联,直接返回该客户购买过的所有产品的QuerySet
product_list = Product.objects.filter(order__client=client)

如果同一个客户有多条订单购买了同一个产品,不想返回重复的产品记录,只需要在后面加.distinct()去重即可:

product_list = Product.objects.filter(order__client=client).distinct()

方案优势

  • 完全使用Django原生ORM API,不需要手写for循环或者列表推导
  • 底层只会生成1条联表查询的SQL,不会出现原写法中「先查所有订单,再逐条查询每个订单对应产品」的N+1性能问题,数据量越大性能优势越明显
  • 返回的是标准的QuerySet对象,后续可以直接链式调用排序、筛选、分页等ORM方法,灵活性更高

如果你不需要完整的Product模型实例,只需要产品的部分字段,还可以用values()或values_list()直接提取指定字段,进一步减少性能开销:

# 直接返回包含产品id、名称的字典列表,不需要实例化Product模型
product_simple_list = client.order_set.values('product__id', 'product__product_name').distinct()

内容的提问来源于stack exchange,提问作者Fabrizio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 07:51:18