Django 不使用 Postgres

Posted

技术标签:

【中文标题】Django 不使用 Postgres【英文标题】:Django distinct not working with Postgres 【发布时间】:2016-08-09 19:15:33 【问题描述】:

我正在配置一个 API 以提取结果列表。这些项目是服装“产品”,有几个“变体”。

我正在尝试使用 distinct 来确保查询集仅返回唯一产品列表 - 而不是由于许多变化而重复多次的同一产品。

过去,我在产品的主键 (id) 上使用了 distinct。但是,下面的代码不起作用。

我在尝试使用“distinct”时收到 500 错误。没有它-我没有错误。我不能在本地测试,因为 SQLite 不喜欢不同的。我正在使用

class InternalListView(APIView):

    renderer_classes = (JSONRenderer, )

    def get(self, request, *args, **kwargs):

        filters = 
        for key, value in request.GET.items():
            key = key.lower()
            if key in countmatch:
                lookup, val = internalmatch[key](value.lower())
                filters[lookup] = val

        qset = (
            Product.objects
            .filter(**filters)
            .distinct('id')
            .order_by('-rating')
            .values('name', 'brand', 'rating')
            .annotate(
                price=F('variation__price__price'),
                id=F('pk'),
                vari=F('variation'),
            )
        )

        for i in qset:
            i['likes'] = random.randint(500, 1000)

        print qset

        return Response(qset.all())

【问题讨论】:

尝试获取 500 错误背后的错误消息,并尽可能发布异常的完整堆栈跟踪。但我的猜测是,错误消息是“SELECT DISTINCT ON 表达式必须匹配初始 ORDER BY 表达式”。带有字段名称的distinct() 是PostgreSQL 扩展,仅当distinct() 给出的字段也提供给第一个order_by() 时才有效。 一般来说,我真的建议安装一个本地 Postgres 服务器来尝试解决此类问题,这并不难。 【参考方案1】:

啊,刚刚想通了。

根据 django 文档 (https://docs.djangoproject.com/en/1.9/ref/models/querysets/#distinct)

distinct 和 order_by 必须相同。

所以这不起作用:

        .distinct('id')
        .order_by('-rating')

但这会起作用:

        .distinct('id')
        .order_by('id')

这是最好的:

        .distinct('rating', 'id')
        .order_by('-rating')

使用选项 3 有什么问题吗?

【讨论】:

distinct('id') 转换为SELECT DISTINCT ON,即PostgreSQL extension。由于distinct() 消除了行,PostgreSQL 要求您指定定义的顺序,否则它将消除随机行,从而导致(可能)不可重复的选择。 这是一个限制,但它必须是不同列的 subset 并且不相同(如果是这样,那就是 django 而不是 pgsql)。 distinct 只会输出您要求的列,因此无法订购其他任何内容。 @AndrewBacker 有趣的是,PostgreSQL (9.4.6) 只有在 order_by 包含至少一列不在不同列表中时才会发出嘶嘶声。即SELECT DISTINCT ON (a, b) a, b, c ... ORDER BY a 有效。 SELECT DISTINCT ON (a, b) a, b, c ... ORDER BY a, c 失败,而 SELECT DISTINCT ON (a, b) a, b, c ... ORDER BY a, b, c。被接受。不过,第一个被接受,在我看来是错误的。您会在输出中获得所有三列,但在第一种情况下,第一行可能是随机的。 @Ycon 选项 3 在语义上与其他两个不同。 distinct('id') 将消除所有具有相同 id 的行。 distinct('id', 'rating') 仅删除具有相同 id AND rating 的重复行。 @dhke 有趣...我没有手动完成 lot 的 psql,但实际上我喜欢这种方式。这是 TSQL 中的一个 hack。我明白为什么#3 可能有效,但它只是事后合理化。也许它已经被 a & b 订购了,所以我们现在可以做 c.. 但如果 b 不存在,它就会混淆。

以上是关于Django 不使用 Postgres的主要内容,如果未能解决你的问题,请参考以下文章

与 django-dynamic-formset 一起使用的 Django Formset 不显示删除链接

在不使用 Django 本身的情况下测试自定义 Django 中间件

Django 不使用 Angularjs

django-pipeline 不压缩

如何在不创建 django 项目的情况下使用 Django 1.8.5 ORM?

Django:不推荐使用对 url() 的字符串视图参数的支持,并将在 Django 1.10 中删除