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にキャストする方法がわからず、見つかりませんでした。生のクエリを使用する必要がありますか、それとも解決策はありますか?あなたの提案を教えてください。
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 から
クエリセットの extra() メソッドを使用:
students.objects.filter(student_id__contains="97318") \
.extra({'stident_id_uint': "CAST(student_id as UNSIGNED)"}) \
.order_by('-student_id_uint')
私は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')