编程错误:函数lower(bigint)不存在(Django,AWS RDS,PostgreSQL)

oipij1gg  于 2023-02-04  发布在  PostgreSQL
关注(0)|答案(2)|浏览(138)

在我的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/ function lower(bigint)不存在行1:...".“作者ID”)分组依据“用户用户”.“ID”排序依据较低(COUN...
提示:没有函数与给定的名称和参数类型匹配。您可能需要添加显式类型转换。
此错误仅出现在RDS部署中。
我试着在django中使用以下命令来对字段进行类型转换:

field = str(field)

但是这并不起作用,有没有什么方法可以在没有lower函数的情况下允许不区分大小写的排序,或者我如何有条件地检查它是一个数字(然后强制转换?)还是文本abd

bnl4lu3b

bnl4lu3b1#

出现这个错误是因为你在一个可能是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
hxzsmxv2

hxzsmxv22#

要回答此评论中的附加问题:
我想知道为什么这段代码可以在我的本地db. sqlite上工作,而不能在RDS上工作...
PostgreSQL lower函数(用于RDS)仅接受文本值。
SQLite lower函数也接受整数,尽管文档中没有明确提到。
这可能与"SQLite uses a more general dynamic type system."有关。另请参见this SO answer
这说明了为什么在本地和生产中使用相同的RDBMS是有利的。
注:
尽管SQLite在执行以下操作时不会发出抱怨

... ORDER BY LOWER("my_integer_field")

结果可能令人惊讶,因为它将在lexicographic order中。
例如
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
将作为文本排序,从而产生
[1, 10, 11, 12, 2, 3, 4, 5, 6, 7, 8, 9]

相关问题