具有多个连接字段的Django ORM查询

时间:2014-07-25 17:12:12

标签: sql django

我怎么能把这个mysql查询变成django ORM?

SELECT search_products.model, search_products.year, search_products.size, search_avg_price.estimated_price
FROM search_products
left JOIN search_avg_price
ON search_products.model=search_avg_price.model and search_products.size=search_avg_price.size and search_products.year=search_avg_price.year

我已经尝试了

latest_products = Products.objects.all().prefetch_related("avg_price")

但这是由django翻译为

SELECT `search_products`.`id`, `search_products`.`size`, `search_products`.`year`, , `search_products`.`model`, `search_products`.`avg_price_id`
FROM `search_products`

latest_products = Products.objects.all().select_related("avg_price")

这是由django翻译为:

SELECT `search_products`.`id`, `search_products`.`size`, `search_products`.`year`, , `search_products`.`model`, `search_products`.`avg_price_id`, `search_avg_price`.`id`, `search_avg_price`.`model`, `search_avg_price`.`size`, `search_avg_price`.`year`, `search_avg_price`.`estimated_price` 
FROM `search_products` 
INNER JOIN `search_avg_price` ON ( `search_products`.`avg_price_id` = `search_avg_price`.`id` )

如果我在数据库中运行上面的SQL,我会得到正确的结果......

编辑:模型和视图

class Avg_price(models.Model):
 model = models.CharField(max_length=50, blank=True)
 size= models.IntegerField(blank=True, null=True)
 year= models.IntegerField(blank=True, null=True)
 estimated_price= models.IntegerField(blank=True, null=True)

class Products(models.Model):
 product_id =models.IntegerField(blank=True, null=True)
 link_id = models.CharField(max_length=200, blank=True)
 location = models.CharField(max_length=200, blank=True)
 model = models.CharField(max_length=50, blank=True)
 size= models.IntegerField(blank=True, null=True)
 price= models.IntegerField(blank=True, null=True)
 year= models.IntegerField(blank=True, null=True)
 type=models.ForeignKey(Type)
 avg_price = models.ForeignKey(Avg_price)

 def __unicode__(self):  # Python 3: def __str__(self):
   return self.location

模板

{% if latest_products %}
  {% for product in latest_products %}
  <ul>
    <li id="col_one">
      <h5>{{product.avg_price.estimated_price}}</h5>
      <h5>{{product.model}}</h5>

2 个答案:

答案 0 :(得分:1)

尝试这样的查询:

qs = Product.objects.filter(
    avg_price__model__isnull=True).filter(
    avg_price__size__isnull=True).filter(
    avg_price__year__isnull=True).values_list(
    'model', 'year', 'size', 'avg_price__estimated_price')

测试:

print(qs.query)

说明:

在您的产品型号中,每次ForeignKey时都会访问avg_price,并且每次返回基于查询的时候,您希望访问该模型中的相对字段NULLLEFT JOIN上。这是关于跨越关系的查找的文档:

https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships

然后values_list让你指定要返回的值。这是关于values_list的文档:

https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.values_list

答案 1 :(得分:1)

您可以将表格列表传递给方法 extra(),并将您的SQL查询的ON条件放入 extra()中的 where 部分

Product.objects.extra(
    tables=['search_avg_price'],
    where=[
        '"search_products"."model"="search_avg_price"."model"',
        '"search_products"."size"="search_avg_price"."size"',
        '"search_products"."year"="search_avg_price"."year"'
   ]
)

详细了解额外信息: https://docs.djangoproject.com/en/1.6/ref/models/querysets/#extra