#python #mysql #django #django-queryset
Вопрос:
Предположим, что у нас есть Q-выражение, подобное этому:
Q(price__lt=160) | Q(publishing_date__year__gte=2016)
Выражение SQL для этого выражения будет:
price < 160 OR YEAR(publishing_date) >= 2016
Мне нужен пакет, который преобразует эти Q
объекты Django в эквивалент SQL. Нравится:
q_obj = Q(price__lt=160) | Q(publishing_date__year__gte=2016)
sql_expression = q_obj_to_sql(q_obj) # Please, recommend if there exists such a thing
Примечание: Хотя Django предоставляет способ преобразования наборов запросов в SQL, но мне нужно конвертировать Q
объекты, а не наборы запросов.
Ответ №1:
вы можете сделать это:
# is a model expample
class MyModel(models.Model):
price = models.IntegerField()
publishing_date = models.DateField()
...
from django.db.models.sql.query import Query
from django.db.models import Q
from django.db.models.sql.compiler import SQLCompiler
from django.db import connection
# your Q filter
_filter = Q(price__lt=160) | Q(publishing_date__year__gte=2016)
_query = Query(MyModel) # replace "MyModel" with your model
_compiler = SQLCompiler(_query, connection, None)
query_str, args = _filter.resolve_expression(_query).as_sql(_compiler, connection)
# query_str is a string, the result is
# '("my_model"."price" < %s OR "my_model"."publishing_date" >= %s)'
# args is a list, result is
# [160, '2016-01-01']
# for replace arguments in query_str
result = query_str % tuple(args)
# WARNING , don't do this !! Security issue with sql injections.
# result :
# '("my_model"."price" < 160 OR "my_model"."publishing_date" >= 2016-01-01)'
Комментарии:
1. В этом случае мне нужна модель, и поля, упомянутые в
Q
запросе, должны быть в модели. Но сценарий, который у меня есть, заключается в том, что у меня нет никакой модели. У меня просто есть несколько поисковых запросов Django, и мне нужно преобразовать их в SQL. Это должно быть независимо от определения модели.2. django нужны модели для построения набора запросов и Q-фильтра для проверки/замены поля на поле моделей , если у вас нет моделей , вы не можете сделать это с помощью django