web-dev-qa-db-ja.com

Django ORMでクエリしているときにcharを整数にキャストするにはどうすればよいですか?

Django ORMを使用して最近開始。このクエリを実行したい

 select student_id from students where student_id like "%97318%" order by CAST(student_id as UNSIGNED) desc;   

ここで、student_idは、クエリ用の整数として必要なCharFieldです。私が試した

  students.objects.filter(student_id__contains "97318").order('-student_id')

正常に動作します。しかし、「Django ORM」を使用した上記の実際のMySQLクエリのように、「student_id」をintにキャストする方法がわからず、見つかりませんでした。生のクエリを使用する必要がありますか、それとも解決策はありますか?あなたの提案を教えてください。

15

extraを使用せずに更新された代替手段は、キャスト関数です(Django 1.10の新機能):

>>> from Django.db.models import FloatField
>>> from Django.db.models.functions import Cast
>>> Value.objects.create(integer=4)
>>> value = Value.objects.annotate(as_float=Cast('integer', FloatField())).get()> 
>>> print(value.as_float)
4.0

https://docs.djangoproject.com/en/1.10/ref/models/database-functions/#cast から

28
erikreed

クエリセットの extra() メソッドを使用:

students.objects.filter(student_id__contains="97318") \
                .extra({'stident_id_uint': "CAST(student_id as UNSIGNED)"}) \
                .order_by('-student_id_uint')
12
catavaran

私はextra()annotate()CASTに試しましたが、関連フィールドではうまく機能せず、JOINSを生成して予期しないクエリセットを生成することがありました。

結局、カスタムルックアップを作成することになりました。

ドキュメントは少数ですが、 here および here にあります

これが私の例です:

@Field.register_lookup
class IntegerValue(Transform):
    # Register this before you filter things, for example in models.py
    lookup_name = 'int'  # Used as object.filter(LeftField__int__gte, "777")
    bilateral = True  # To cast both left and right

    def as_sql(self, compiler, connection):
        sql, params = compiler.compile(self.lhs)
        sql = 'CAST(%s AS UNSIGNED)' % sql
        return sql, params

次に、以下が機能するはずです:

students.objects.filter(student_id__int__gte="97318").order('-student_id')
3
KinoP