如何用Django ORM实现类LEFT JOIN查询:关联单张产品图片
Django ORM 实现指定查询需求
现有模型定义
models.py 中的模型代码:
class Products(models.Model): name = models.CharField() price = models.IntegerField() class Products_Images(models.Model): products = models.ForeignKey(Products) image = models.ImageField() name = models.CharField()
查询需求
查询价格≥50的Products数据,且每个产品仅关联一张名称包含“pizza”的Products_Images图片(无匹配图片则返回空),对应原生SQL如下:
SELECT Products.*,Products_Images.* FROM Products LEFT JOIN Products_Images on Products.id=Products_Images.product_id AND Products_Images.name LIKE '%pizza%' WHERE Products.price >= 50
ORM 实现方案
方案一:使用Prefetch预筛选关联图片
通过Prefetch对象在预取关联数据时添加筛选条件,同时过滤产品价格,适合需要完整图片实例的场景:
from django.db.models import Prefetch # 定义筛选条件:名称包含"pizza"的图片(__icontains对应LIKE '%pizza%',不区分大小写) pizza_image_queryset = Products_Images.objects.filter(name__icontains='pizza') # 查询价格≥50的产品,并预取匹配的图片到指定属性 products = Products.objects.filter(price__gte=50).prefetch_related( Prefetch('products_images_set', queryset=pizza_image_queryset, to_attr='matched_pizza_images') ) # 遍历结果,每个产品的matched_pizza_images是匹配的图片列表,取第一个即为单张匹配图片 for product in products: target_image = product.matched_pizza_images[0] if product.matched_pizza_images else None # 可访问target_image.image、target_image.name等属性
方案二:使用Subquery关联单张匹配图片
通过子查询直接在主查询中获取匹配的图片字段,更贴近原生SQL的左连接逻辑,性能更优,适合仅需图片部分字段的场景:
from django.db.models import OuterRef, Subquery # 子查询:获取当前产品对应的第一张名称含"pizza"的图片 image_subquery = Products_Images.objects.filter( products_id=OuterRef('id'), name__icontains='pizza' ).values('image', 'name')[:1] # 给产品添加匹配图片的字段,无匹配则为None products = Products.objects.filter(price__gte=50).annotate( pizza_image=Subquery(image_subquery.values('image')), pizza_image_name=Subquery(image_subquery.values('name')) ) # 直接访问产品的注解字段 for product in products: print(f"产品:{product.name},价格:{product.price},匹配图片:{product.pizza_image},图片名称:{product.pizza_image_name}")
内容的提问来源于stack exchange,提问作者Yuretz
相关产品推荐
相关产品推荐

