【问题标题】:ProgrammingError: function lower(bigint) does not exist (Django, AWS RDS, PostgreSQL)ProgrammingError: 函数 lower(bigint) 不存在 (Django, AWS RDS, PostgreSQL)
【发布时间】:2021-06-07 14:23:49
【问题描述】:

在我的 Django Rest Framework 项目中,我有一个自定义的 filter_backends,它允许不区分大小写地进行过滤:

class CaseInsensitiveOrderingFilter(OrderingFilter):
    
    def filter_queryset(self, request, queryset, view):
        ordering = self.get_ordering(request, queryset, view)
    
        if ordering:
            new_ordering = []
            for field in ordering:
             #   field = str(field)
                print(Lower(field))
                if field.startswith('-'):
                    new_ordering.append(Lower(field[1:]).desc())
                else:
                    new_ordering.append(Lower(field).asc())
            return queryset.order_by(*new_ordering)
    
        return queryset

这在开发中运行良好。

现在我在 elastic beanstalk 上托管 django 应用程序,并通过亚马逊关系数据库服务 (RDS) 配置了一个 postgresql 数据库。

当我现在尝试调用 API 时,我收到此错误:

/api/profile_list/ 函数 lower(bigint) 处的 ProgrammingError 不会 存在 LINE 1: ..."."author_id") GROUP BY "user_user"."id" ORDER BY LOWER(COUN...

提示:没有函数匹配给定的名称和参数类型。你 可能需要添加显式类型转换。

此错误仅出现在 RDS 部署中。

我尝试在 django 中输入转换字段:

field = str(field) 

但这不起作用。有没有办法在没有较低功能的情况下允许不区分大小写的排序,或者我如何有条件地检查它是数字(然后强制转换?)还是文本 abd

【问题讨论】:

  • 为什么您甚至需要对 number 进行不区分大小写的排序?显然,您想在使用 Lower 函数之前检查您的字段实际上是什么。
  • 我想知道为什么这段代码可以在我的本地 db.sqlite 上工作,但不能在 RDS 上工作。使用Lower前应该如何检查类型?

标签: django postgresql amazon-web-services amazon-rds case-insensitive


【解决方案1】:

您收到错误是因为您在可能是 IntegerField 或其他内容的字段上使用了 Lower。您想在实际使用 Lower 之前检查您的字段是什么:

from django.db import models


def get_field_type(field_name, queryset):
    stripped_field_name = field_name.lstrip('-')
    if stripped_field_name in queryset.query.annotations:
        return queryset.query.annotations[stripped_field_name].output_field
    return queryset.model._meta.get_field(stripped_field_name)


class CaseInsensitiveOrderingFilter(OrderingFilter):
    
    def filter_queryset(self, request, queryset, view):
        ordering = self.get_ordering(request, queryset, view)
    
        if ordering:
            new_ordering = []
            for field in ordering:
                if not isinstance(get_field_type(field, queryset), (models.CharField, models.TextField)):
                    # Most of the character type fields inherit from CharField.
                    # I might miss a few fields here so you would need to make sure
                    new_ordering.append(field)
                elif field.startswith('-'):
                    new_ordering.append(Lower(field[1:]).desc())
                else:
                    new_ordering.append(Lower(field).asc())
            return queryset.order_by(*new_ordering)
    
        return queryset

【讨论】:

  • 如何为我在序列化程序中声明的其他字段执行此操作?我没有模型类型的地方......例如我将“number_of_authors”保存在 Count(authors.id)
  • @alexrogo 我已经编辑了答案并添加了一个函数来获取字段类型。做检查。
猜你喜欢
  • 2021-11-13
  • 2020-08-12
  • 1970-01-01
  • 2018-05-05
  • 1970-01-01
  • 2016-10-12
  • 2019-06-08
  • 2016-11-08
  • 2016-04-11
相关资源
最近更新 更多