Порядок фильтрации в django

Мне интересно фильтровать таблицу по django orm в определенном порядке. По сути, это простой поиск по двум полям — имени и описанию. Я хочу отсортировать результат сначала по параллелизмам поля «имя», а затем по параллелизмам поля «описание». Вот пример необработанного sql:

WITH checkpoints AS (SELECT * FROM checkpoints_view WHERE ...) SELECT * FROM checkpoints WHERE name ILIKE '%KEYWORD%' UNION ALL SELECT * FROM checkpoints WHERE description ILIKE '%KEYWORD%' AND name NOT ILIKE '%KEYWORD%';

Как я могу сгенерировать такой sql в форме django?

Спасибо всем

P.S.: извините за мой английский, если я был не прав, я из неанглоязычной страны

class Checkpoint(models.Model, ReadOnlyModel):
    id = models.IntegerField(primary_key=True) 
    name = models.CharField(max_length=255, verbose_name='Наименование')
    code_number = models.CharField(max_length=255, verbose_name="Код остановки")
    description = models.CharField(max_length=255, verbose_name="Описание")
    coordinate = models.PointField(verbose_name="Координата")
    routes = ArrayField(models.IntegerField())
    dates = ArrayField(models.DateField()) 

    class Meta: 
        db_table = 'checkpoints_view' 
        managed = False

Почти все вы правы, но я хочу, чтобы результат был сначала упорядочен по строкам, прошедшим фильтр поля имени, а затем уже после всего этого - по строкам, прошедшим фильтр поля описания


person Bergutov Ruslan    schedule 29.05.2017    source источник
comment
поделитесь пожалуйста моделью   -  person aliva    schedule 29.05.2017


Ответы (2)


Я думаю, что ваш код можно написать без CTE:

Checkpoint.objects.filter(
    Q(name__icontains='keyword') |
    (~Q(name__icontains='keyword') & Q(description__icontains='keyword')))
person Eugene Morozov    schedule 29.05.2017
comment
какая у тебя проблема?? почему вы минусуете только мой ответ?? что я тебе сделал ?? кто-то еще дал тот же ответ, но конкретно вы отрицаете мой ответ? - person Exprator; 29.05.2017
comment
@Exprator, вы здесь, чтобы пожинать легкую репутацию SO. Другое упомянутое вами решение вернет правильный результат, хотя это и не оптимальное решение. Ваше решение не решает проблему - если вы подумаете или попробуете, вы увидите, что оно даст результаты, отличные от результатов запроса, опубликованного в вопросе. Ничего личного, я увидел неправильный ответ и проголосовал за него. - person Eugene Morozov; 29.05.2017
comment
высказывание «не оптимальное решение» заставило меня задуматься, потому что я всегда использую свое решение (я думаю, что оно более читабельно и не знал, что оно может быть менее эффективным), поэтому попробовал оба решения (мое и ваше) на простой модели django с очень простой запрос (pk>10) or (pk < 10 and pk !=3) и проверенный sql-запрос django с использованием print(q.query), они оба сгенерировали один и тот же sql-запрос. - person aliva; 29.05.2017
comment
Я не уверен насчет сложных запросов, возможно, для сложных запросов все по-другому. - person aliva; 29.05.2017
comment
@aliva лучше установить пакет django-extensions и использовать ./manage.py debugsqlshell, это удобнее и будет выводить все запросы в консоль. Я был неправ, когда сказал, что ваше решение не является оптимальным - я проверил, и кажется, что Django также генерирует оптимальный SQL-запрос в вашем случае. - person Eugene Morozov; 29.05.2017

Насколько мне известно, Django ORM не использует CTE в генерируемых им запросах. Это потому, что они имеют разное поведение в разных СУБД и вообще не поддерживаются в mysql и sqlite.

Поэтому, если вы хотите использовать CTE в своем запросе, единственным вариантом является необработанный запрос. Что-то типа

queryset = MyModel.objects.raw('WITH checkpoints AS (SEL ....')
person e4c5    schedule 29.05.2017
comment
это проблема, она уже работает на необработанном sql, но я хочу реализовать это в django orm. Спасибо за ответ. - person Bergutov Ruslan; 29.05.2017
comment
Кстати, я не имею в виду строгое использование ключевого слова WITH, это может быть всего два выбора с объединением. - person Bergutov Ruslan; 29.05.2017
comment
Вы задали вопрос, на который мы ответили. Что вы имели в виду, мы не можем ответить. - person e4c5; 29.05.2017