python - django admin 错误地将 order by 添加到查询中

标签 python mysql django django-admin

多亏了 django 调试工具栏,我注意到每个 django 管理列表页面总是在我的所有查询中添加一个“ORDER BY id DESC”,即使我手动覆盖 admin.ModelAdmin 的 get_queryset 方法(我通常这样做是因为我想在我的一些管理页面上进行自定义排序)

我想这其实没什么好担心的,但这是数据库需要做的额外排序操作,即使它根本没有意义。

有什么办法可以避免这种情况吗?似乎在某些模型上(甚至不是所有模型)如果我添加订购元数据,那么它不会自动按 ID 添加订单,但它会按该字段添加,这也是我不知道的' 想要,因为这样做会将该 order by 添加到代码中的所有其他查询中。

编辑:似乎罪魁祸首在 ChangeList 的 django.contrib.admin.views.main 中,在第 316 行的函数 get_ordering 上(django 1.7.10)

 pk_name = self.lookup_opts.pk.name
    if not (set(ordering) & set(['pk', '-pk', pk_name, '-' + pk_name])):
        # The two sets do not intersect, meaning the pk isn't present. So
        # we add it.
        ordering.append('-pk')

我想知道这背后的原因是什么......

编辑: 为了提高性能,并且由于 MySQL(和 InnoDB)在没有给出 order by 时以聚簇索引顺序返回数据,我可以安全地删除该 id 附加。 这样做很简单,我只是扩展了django的ChangeList并修改了get_ordering方法。之后,制作了一个自定义管理模型,该模型从 ModelAdmin 扩展并覆盖 get_changelist 方法以返回上述类。

希望对大家有帮助:)

最佳答案

遇到与这个问题完全相同的问题,当我已经有唯一排序时,由于 ID 排序,管理查询集慢了 4 倍。感谢@user1777914 和他的工作,我没有其他负载超时!如果其他人遭受同样的痛苦,我只是在这里添加这个答案以清楚起见。正如 user1777914 提到的扩展 ChangeList:

class NoPkChangeList(ChangeList):
    def get_ordering(self, request, queryset):
        """
        Returns the list of ordering fields for the change list.
        First we check the get_ordering() method in model admin, then we check
        the object's default ordering. Then, any manually-specified ordering
        from the query string overrides anything. Finally, WE REMOVE the primary
        key ordering field.
        """
        params = self.params
        ordering = list(self.model_admin.get_ordering(request) or self._get_default_ordering())
        if ORDER_VAR in params:
            # Clear ordering and used params
            ordering = []
            order_params = params[ORDER_VAR].split('.')
            for p in order_params:
                try:
                    none, pfx, idx = p.rpartition('-')
                    field_name = self.list_display[int(idx)]
                    order_field = self.get_ordering_field(field_name)
                    if not order_field:
                        continue  # No 'admin_order_field', skip it
                    # reverse order if order_field has already "-" as prefix
                    if order_field.startswith('-') and pfx == "-":
                        ordering.append(order_field[1:])
                    else:
                        ordering.append(pfx + order_field)
                except (IndexError, ValueError):
                    continue  # Invalid ordering specified, skip it.

        # Add the given query's ordering fields, if any.
        ordering.extend(queryset.query.order_by)

        # Ensure that the primary key is systematically present in the list of
        # ordering fields so we can guarantee a deterministic order across all
        # database backends.
        # pk_name = self.lookup_opts.pk.name
        # if not (set(ordering) & {'pk', '-pk', pk_name, '-' + pk_name}):
        #     # The two sets do not intersect, meaning the pk isn't present. So
        #     # we add it.
        #     ordering.append('-pk')

        return ordering

然后在您的 ModelAdmin 中覆盖 get_changelist:

class MyAdmin(ModelAdmin):
    def get_changelist(self, request, **kwargs):
        return NoPkChangeList

关于python - django admin 错误地将 order by 添加到查询中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32419190/

相关文章:

python - 如果定义了数据列限制,则按默认值填充行

mysql - 使用 Qt 连接数据库 : Failed?

php - mysql表中导入的表情符号和json_encode

Django - save() 更新重复键

Django 身份验证后端

python - 如何将带有多个字符的定界符的 .text 解析为 pandas df?

python - 如何实现适用于负数的 CountingSort?

Python property() 返回未列出的字段?

php - 查询不想执行

django - Django REST Framework(DRF):将当前用户ID设置为字段值