簡體   English   中英

Django使用自定義排序規則進行查詢

[英]Django making a query with custom collation

是否可以使用與數據庫表不同的排序規則進行查詢?

使用extra()有點麻煩。 現在可以使用Func()表達式實現類似的功能(自 Django 1.8 起):

username_ci = Func(
    'username',
    function='utf8_general_ci',
    template='(%(expressions)s) COLLATE "%(function)s"')

這可以在annotate()

User.objects.annotate(uname_ci=username_ci).filter(uname_ci='joeblow').exists()

或者在order_by()在排序時覆蓋默認的排序規則:

User.objects.order_by(username_ci)

現在,它看起來仍然很亂,但是如果您查看Func()的文檔和代碼,您會發現將其子類化並制作可重用的排序規則設置器非常容易。

我在 Postgres 數據庫中使用了這個技巧。

以下是如何使用特定的排序規則而不是給定表/列的默認排序規則。 我假設您總是希望它不區分大小寫 utf8_general_ci,但是您可以輕松地在代碼中更改它或將其添加為變量。

請注意使用 params kwarg 而不是 db 文字函數。 參數存在的目的完全相同。

def iexact(**kw):
    fields = [['%s=%%s collate utf8_general_ci'%field,value] for (field,value) in kw.items()]
    return dict(where=[f[0] for f in fields], params=[f[1] for f in fields])

if User.objects.extra(**iexact(username='joeblow')).exists():
    status = "Found a user with this username!"

我用一點技巧解決了這個問題;

Django的extra方法和raw方法一樣,都是直接使用查詢語句;

MyModel.objects.extra(where=["name LIKE '%%" + name + "%%' COLLATE utf8_general_ci"])

但是像這個 sql 注入是可能的。 我們需要轉義name變量。 我搜索了很多只為 db 轉義字符串的函數。 MySQL-python包中找到了一個,但它無法轉義 unicode 字符串。 包也有literal方法connection但要使用它,我們需要一個實例(也許它是為了 db 特性)。

最后我使用了 Django 的db.connection.cursor

from django.db import connection
cursor = connection.cursor()
name = cursor.db.connection.literal(name)[1:-1]  # [1:-1] excluding quotes

通過這種方式,我們還需要一個實例,但我想這不需要數據庫連接。 而且我想這種方法與數據庫無關。 如果我錯了,請糾正我。

上述解決方案有效。 如果獲得相反的順序,請使用以下代碼段

sort_value = sort.strip()
if sort_value in ['name', '-name']:
    sort = Func('name', function='C', template='(%(expressions)s) COLLATE "%(function)s"')
if sort_value in ['-name']:
    f_res = queryset.order_by(sort).reverse()
else:
    f_res = queryset.order_by(sort)
return f_res

暫無
暫無

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

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