【问题标题】:How to build up a nested query using Django's Database API如何使用 Django 的数据库 API 构建嵌套查询
【发布时间】:2017-11-01 15:12:15
【问题描述】:

我需要在 Django 中创建以下 PostgreSQL 语句的查询集。

SELECT * FROM 
(
SELECT DISTINCT ON("atech_cars".
    "model")
"atech_cars".
"make", "atech_cars".
"model", "atech_cars".
"trim"
FROM "atech_cars"
WHERE(UPPER("atech_cars".
        "make"::text) = UPPER('Ford') AND "atech_cars".
    "model"
    IN(SELECT U0.
        "char_value"
        AS Col1 FROM "clf_atech_filter_cache"
        U0 WHERE U0.
        "filter_id" = 7))
) Sub 
ORDER BY 
CASE WHEN ("model" = 'xD') THEN 0 
WHEN ("model" = 'Cayenne') THEN 1 
WHEN ("model" = 'Elantra') THEN 297 ELSE NULL END ASC

这是我想在最后用 queryset 生成的查询。

我已经创建了以下语句的查询集。

SELECT DISTINCT ON("atech_cars".
    "model")
"atech_cars".
"make", "atech_cars".
"model", "atech_cars".
"trim"
FROM "atech_cars"
WHERE(UPPER("atech_cars".
        "make"::text) = UPPER('Ford') AND "atech_cars".
    "model"
    IN(SELECT U0.
        "char_value"
        AS Col1 FROM "clf_atech_filter_cache"
        U0 WHERE U0.
        "filter_id" = 7))

所以最终,我正在寻找以下语句的查询集。

SELECT * FROM 
(
<Queryset>
) Sub 
ORDER BY 
CASE WHEN ("model" = 'xD') THEN 0 
WHEN ("model" = 'Cayenne') THEN 1 
WHEN ("model" = 'Elantra') THEN 297 ELSE NULL END ASC

这是我创建的 django 查询集,但它不起作用。

class ATechCarModelFilter(Filter):

    def filter(self, qs, value):
        # trim filter_id = 9 in atech_filter
        trims = ClfCacheModel.objects.filter(filter_id = 9).values_list('char_value', flat=True).order_by("counter")
        preserved = Case(*[When(trim=trim, then=pos) for pos, trim in enumerate(trims)])
        return qs.filter(model__iexact = value).filter(trim__in=trims).order_by(preserved)

这里,qs 指的是 BModel 的查询集

如何在已有的查询对象上构建?

我做错了什么?

这是所要求的模型

class BModal(models.Model):
    char_value = models.CharField(max_length=2048, blank=True, null=True)
    counter = models.IntegerField()

    class Meta:
        managed = False
        db_table = 'filter_cache'

class AModel(models.Model):
    make = models.CharField(max_length=200, primary_key=True)
    model = models.CharField(max_length=200, primary_key=True)
    trim = models.CharField(max_length=200)

    class Meta:
        managed = False
        db_table = 'amodel'

这就是我想要的。

1) AModel 和 BModel 目前不相关。

2) 从 AModel 表中获取模型列表,然后根据该列表的顺序,我想按照 BModel 中的列表顺序进行排序。

3) 之后,我想用 distint("model") 删除重复的项目

使用注释更新了 ATechCarMakeFilter():

class ATechCarMakeFilter(Filter):
    def filter(self, qs, value):
      # model filter_id = 7 in atech_filter
      models = ClfCacheModel.objects.filter(filter_id = 7).values_list('char_value', flat=True).order_by("counter")
      preserved = Case(*[When(model=model, then=pos) for pos, model in enumerate(models)], default=None, output_field=IntegerField())
      qs = qs.filter(make__iexact = value).filter(model__in=models).distinct("model")        
      return qs.annotate(ordering=preserved).order_by("-ordering")  

【问题讨论】:

  • 欢迎来到 SO。我对您的问题进行了一些编辑,希望它们对您有所帮助。不过,总的来说,您的问题很好,因为您详细列出了您尝试做的所有事情。如果是我,我会尝试一个更简单的查询来了解如何做到这一点。如果您尝试使用更简单的查询,但仍然无法让嵌套查询在 Django 中工作,您可以编辑自己的问题以放入更简单的查询,并可能从 Django 社区获得更多回复。我自己不是 Django 用户,所以我不会提供任何直接帮助。如果找到答案,您可以回答自己的问题并接受。
  • @WattsInABox 谢谢
  • Django ORM 用于从 OOP 模型及其关系创建 SQL。所以,SQL 应该是结果,而不是起点。为了创建正确的 ORM 查询,请提供您的模型并告诉我们您想从中得到什么。
  • 感谢您的支持@KlausD。我已经更新了描述以及模型的更多细节。
  • 抱歉,我仍然不知道您要归档什么。

标签: python django postgresql django-queryset


【解决方案1】:

好的,我想我明白你在这里发生了什么。您可以使用您正在查找的案例语句注释您的查询集,然后按此排序

from django.db.models import Count, Case, When, IntegerField

class ATechCarModelFilter(Filter):
     def filter(self, qs, value):
        qs = ... 
        ...  # previous filters
        qs.annotate(
            ordering=Case(
                When(model='xD', then=0),
                When(model='Cayenne', then=1),
                When(model='Elantra', then=297),
                default=None,
                output_field=IntegerField()
            )
        ).order_by('-ordering')

【讨论】:

  • 我已经用注释更新了 ATechCarModelFilter 如下。注意:我已经用更新的ATechCarModelFilter 更新了描述,但我收到了以下错误消息。无法解析表达式类型,未知 output_field。谢谢
  • 我已按照您的要求更新了 ATechCarMakeFilter 中的过滤器,但出现了同样的错误。更新了描述。
猜你喜欢
  • 2019-11-23
  • 2012-05-06
  • 1970-01-01
  • 1970-01-01
  • 2018-08-23
  • 2021-01-22
  • 2018-10-15
  • 2021-10-21
  • 1970-01-01
相关资源
最近更新 更多