簡體   English   中英

編程錯誤:function lower(bigint) 不存在(Django、AWS RDS、PostgreSQL)

[英]ProgrammingError: function lower(bigint) does not exist (Django, AWS RDS, PostgreSQL)

在我的 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

這在開發中工作正常。

現在,我在彈性 beantalk 上托管了 django 應用程序,並通過亞馬遜關系數據庫服務 (RDS) 配置了一個 postgresql 數據庫。

當我現在嘗試撥打 API 時,出現以下錯誤:

ProgrammingError at /api/profile_list/ function lower(bigint) does not exist LINE 1: ..."."author_id") GROUP BY "user_user"."id" ORDER BY LOWER(COUN...

提示:沒有 function 匹配給定的名稱和參數類型。 您可能需要添加顯式類型轉換。

此錯誤僅出現在 RDS 部署中。

我嘗試在 django 中輸入以下字段:

field = str(field) 

但這是行不通的。 有什么方法可以在沒有較低的 function 的情況下允許不區分大小寫的排序,或者我如何有條件地檢查它是一個數字(然后轉換?)或文本 abd

您收到錯誤是因為您在可能是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

要回答此評論中的其他問題:

我想知道為什么這段代碼適用於我的本地 db.sqlite,但不適用於 RDS。 ...

PostgreSQL lower function(在 RDS 上使用) 只接受文本值

SQLite lower function 也接受整數,盡管文檔中沒有明確提及

這可能與“SQLite 使用更通用的動態類型系統”這一事實有關。 另請參閱此 SO 答案

這說明了為什么在本地和生產中使用相同的 RDBMS 是有利的。

筆記:

雖然 SQLite 在你做類似的事情時不會抱怨

... ORDER BY LOWER("my_integer_field")

結果可能會令人驚訝,因為它將按字典順序排列

例如

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

將被排序為文本,導致

[1, 10, 11, 12, 2, 3, 4, 5, 6, 7, 8, 9]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM