如何用Django extra查询集修饰符获取卖家与潜在买家共有的车辆
Django: 使用extra查询集获取Seller关联的被PotentialBuyer选中的车辆列表
首先先修正下你的模型定义(得继承models.Model才能用Django ORM的完整功能,之前写的object是不对的):
from django.db import models class Seller(models.Model): type = models.CharField(max_length=100) # 示例字段类型,可根据实际需求调整 name = models.CharField(max_length=100) cars = models.ManyToManyField('Car') class PotentialBuyer(models.Model): name = models.CharField(max_length=100) cars = models.ManyToManyField('Car') class Car(models.Model): extra_field = models.CharField(max_length=100) extra_field2 = models.IntegerField()
针对你想要的需求——获取Seller对象时,用extra()查询集修饰符筛选出已被PotentialBuyer选中的车辆,我来给出具体实现:
使用extra()的实现方式
首先要记住Django自动生成的多对多中间表命名规则:应用名_模型名_关联字段名,比如你的应用叫car_shop,那PotentialBuyer和Car的中间表就是car_shop_potentialbuyer_cars,Car表是car_shop_car,你要替换成自己实际的应用名称。
class Seller(models.Model): # ... 上面的字段定义 ... def markPending(self): # 筛选当前卖家名下被至少一个潜在买家选中的车辆 return self.cars.extra( select={ # 用EXISTS子查询判断车辆是否被任何PotentialBuyer选中 'is_pending': """ EXISTS ( SELECT 1 FROM car_shop_potentialbuyer_cars WHERE car_shop_potentialbuyer_cars.car_id = car_shop_car.id ) """ }, # 只保留被选中的车辆 where=['is_pending = 1'] )
如果还想知道每辆车被多少个潜在买家选中,可以调整成这样:
def markPending(self): return self.cars.extra( select={ 'pending_count': """ SELECT COUNT(*) FROM car_shop_potentialbuyer_cars WHERE car_shop_potentialbuyer_cars.car_id = car_shop_car.id """ } ).filter(pending_count__gt=0)
重要提醒:extra()已过时,推荐用现代ORM方法
得说下,extra()在Django 1.8之后就被标记为过时了,未来版本可能会被移除,所以更推荐用annotate()结合Exists子查询的方式,代码更清晰还兼容后续版本:
from django.db.models import Exists, OuterRef class Seller(models.Model): # ... 字段定义 ... def markPending(self): # 定义子查询:检查车辆是否在PotentialBuyer的关联表中 pending_subquery = PotentialBuyer.cars.through.objects.filter( car_id=OuterRef('id') ) # 给车辆添加is_pending注解,再筛选出被选中的 return self.cars.annotate( is_pending=Exists(pending_subquery) ).filter(is_pending=True)
这种方式不用硬编码表名,更符合Django ORM的设计思路,维护起来也更方便。
内容的提问来源于stack exchange,提问作者Forethinker
相关产品推荐
相关产品推荐

