В чем разница между фильтром с несколькими аргументами и сетевым фильтром в django?
Разница между фильтром с несколькими аргументами и цепным фильтром в django
Ответ 1
Как видно из сгенерированных операторов SQL, разница не в "ИЛИ", как могут подозревать некоторые. Именно так ГДЕ и СОЕДИНЯЕТСЯ.
Пример 1 (та же самая объединенная таблица): из https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships
Blog.objects.filter(
entry__headline__contains='Lennon',
entry__pub_date__year=2008)
Это даст вам все блоги, у которых есть одна запись с обоими (entry__headline__contains='Lennon') AND (entry__pub_date__year=2008)
, чего вы и ожидали от этого запроса.
Результат:
Blog with {entry.headline: 'Life of Lennon', entry.pub_date: '2008'}
Пример 2 (цепочка)
Blog.objects.filter(
entry__headline__contains='Lennon'
).filter(
entry__pub_date__year=2008)
Это будет охватывать все результаты из примера 1, но будет генерировать немного больший результат. Потому что сначала он фильтрует все блоги с помощью (entry__headline__contains='Lennon')
, а затем из фильтров результатов (entry__pub_date__year=2008)
.
Разница в том, что он также даст вам такие результаты, как:
Один блог с несколькими записями
{entry.headline: '**Lennon**', entry.pub_date: 2000},
{entry.headline: 'Bill', entry.pub_date: **2008**}
Когда первый фильтр был оценен, книга включается из-за первой записи (хотя в ней есть другие записи, которые не совпадают). Когда второй фильтр оценивается, книга включается из-за второй записи.
Одна таблица: Но если в запросе не используются объединенные таблицы, как, например, в Yuji и DTing. Результат тот же.
Ответ 2
Случай, когда результаты "множественных аргументов filter-query" различаются, а затем "clained-filter-query", следующие:
Выбор ссылочных объектов на основе ссылок объектов и отношений - один-ко-многим (или многим-ко-многим).
Несколько фильтров:
Referenced.filter(referencing1_a=x, referencing1_b=y) # same referencing model ^^ ^^
Цепные фильтры:
Referenced.filter(referencing1_a=x).filter(referencing1_b=y)
Оба запроса могут выдавать разные результаты:
Если более одного строки в ссылочной моделиReferencing1
могут ссылаться на одну и ту же строку в ссылки-модельReferenced
. Это может иметь место вReferenced
:Referencing1
имеют либо 1: N (один для многих), либо N: M (многие для многих) отношение корабль.
Пример:
Рассмотрим, что мое приложение my_company
имеет две модели Employee
и Dependent
. У сотрудника в my_company
может быть больше, чем иждивенцев (другими словами, зависимым может быть сын/дочь одного сотрудника, а у сотрудника может быть более одного сына/дочери).
Ehh, предполагая, что жена мужа и жена не могут работать в my_company
. Я взял пример 1: m
Итак, Employee
- это ссылочная модель, на которую может ссылаться больше, чем Dependent
, которая является ссылочной моделью. Теперь рассмотрим состояние отношения следующим образом:
Employee: Dependent: +------+ +------+--------+-------------+--------------+ | name | | name | E-name | school_mark | college_mark | +------+ +------+--------+-------------+--------------+ | A | | a1 | A | 79 | 81 | | B | | b1 | B | 80 | 60 | +------+ | b2 | B | 68 | 86 | +------+--------+-------------+--------------+
Зависимый
a1
относится к сотрудникуA
и зависимымb1, b2
ссылкам к сотрудникуB
.
Теперь мой запрос:
Найти всех сотрудников, у которых есть сын/дочь, имеет отличительные знаки (скажем >= 75%) в колледже и школе?
>>> Employee.objects.filter(dependent__school_mark__gte=75,
... dependent__college_mark__gte=75)
[<Employee: A>]
Результат "A" зависит от "a1", имеет отличительные знаки в колледже, а школа зависит от сотрудника "A". Примечание "B" не выбрано, потому что у ребенка "B" есть метки отличия как в колледже, так и в школе. Реляционная алгебра:
Сотрудник ⋈ (school_mark >= 75 AND college_mark >= 75) Dependent
Во втором случае мне нужен запрос:
Найдите всех сотрудников, у которых некоторые иждивенцы имеют отличительные знаки в колледже и школе?
>>> Employee.objects.filter(
... dependent__school_mark__gte=75
... ).filter(
... dependent__college_mark__gte=75)
[<Employee: A>, <Employee: B>]
В этот раз "B" также выбран, потому что "B" имеет двух детей (более одного!), один имеет знак отличия в школе "b1", а другой имеет знак отличия в колледже "b2".
Заказ фильтра не имеет значения, мы также можем написать выше запрос как:
>>> Employee.objects.filter(
... dependent__college_mark__gte=75
... ).filter(
... dependent__school_mark__gte=75)
[<Employee: A>, <Employee: B>]
результат такой же! Реляционная алгебра может быть:
(Employee ⋈ (school_mark >= 75) Dependent) ⋈ (college_mark >= 75) Dependent
Примечание:
dq1 = Dependent.objects.filter(college_mark__gte=75, school_mark__gte=75)
dq2 = Dependent.objects.filter(college_mark__gte=75).filter(school_mark__gte=75)
Выводит тот же результат: [<Dependent: a1>]
Я проверяю целевой SQL-запрос, сгенерированный Django с помощью print qd1.query
и print qd2.query
, оба они одинаковы (Django 1.6).
Но семантически оба разные. сначала выглядит как простой раздел σ [school_mark >= 75 AND college_mark >= 75] (Dependent), а второй - медленный вложенный запрос: σ [school_mark >= 75] (σ [college_mark >= 75] (зависимый)).
Если вам нужно Code @codepad
btw, он приведен в документации @Объяснение многозначных отношений Я только что добавил пример, я думаю, что это будет полезно для кого-то новый.
Ответ 3
В большинстве случаев для запроса есть только один возможный набор результатов.
Использование для цепочки фильтров происходит, когда вы имеете дело с m2m:
Рассмотрим это:
# will return all Model with m2m field 1
Model.objects.filter(m2m_field=1)
# will return Model with both 1 AND 2
Model.objects.filter(m2m_field=1).filter(m2m_field=2)
# this will NOT work
Model.objects.filter(Q(m2m_field=1) & Q(m2m_field=2))
Другие примеры приветствуются.
Ответ 4
Разница в производительности огромна. Попробуйте и посмотрите.
Model.objects.filter(condition_a).filter(condition_b).filter(condition_c)
на удивление медленный по сравнению с
Model.objects.filter(condition_a, condition_b, condition_c)
Как уже упоминалось в "Эффективном Django ORM",
- QuerySets поддерживает состояние в памяти
- Цепочка запускает клонирование, дублируя это состояние
- К сожалению, QuerySets поддерживает много состояния
- Если возможно, не связывайте более одного фильтра
Ответ 5
Вы можете использовать модуль подключения, чтобы просмотреть сырые SQL-запросы для сравнения. Как объяснил Юджи, по большей части они эквивалентны, как показано здесь:
>>> from django.db import connection
>>> samples1 = Unit.objects.filter(color="orange", volume=None)
>>> samples2 = Unit.objects.filter(color="orange").filter(volume=None)
>>> list(samples1)
[]
>>> list(samples2)
[]
>>> for q in connection.queries:
... print q['sql']
...
SELECT `samples_unit`.`id`, `samples_unit`.`color`, `samples_unit`.`volume` FROM `samples_unit` WHERE (`samples_unit`.`color` = orange AND `samples_unit`.`volume` IS NULL)
SELECT `samples_unit`.`id`, `samples_unit`.`color`, `samples_unit`.`volume` FROM `samples_unit` WHERE (`samples_unit`.`color` = orange AND `samples_unit`.`volume` IS NULL)
>>>
Ответ 6
Если на этой странице вы узнаете, как динамически создавать django-запрос с несколькими фильтрами цепочки, но вам нужны фильтры типа AND
вместо OR
, рассмотрите возможность использования объекты Q.
Пример:
# First filter by type.
filters = None
if param in CARS:
objects = app.models.Car.objects
filters = Q(tire=param)
elif param in PLANES:
objects = app.models.Plane.objects
filters = Q(wing=param)
# Now filter by location.
if location == 'France':
filters = filters & Q(quay=location)
elif location == 'England':
filters = filters & Q(harbor=location)
# Finally, generate the actual queryset
queryset = objects.filter(filters)
Ответ 7
из django.db.models import Q
& is = Boolean (i) | is = Boolean (o)
models.objects.filter(Q (id = self.kwargs ['pk']) и Q (date = self.kwargs ['date'])) models.objects.filter(Q (id = self.kwargs ['pk) ']) | Q (date = self.kwargs [' date ']))
Ответ 8
Если требуется a и b, то
and_query_set = Model.objects.filter(a=a, b=b)
если требуется a, а b, то
chaied_query_set = Model.objects.filter(a=a).filter(b=b)
Официальные документы: https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships
Похожие сообщения: Цепочка нескольких фильтров() в Django, это ошибка?
Ответ 9
Есть разница, когда у вас есть запрос к связанному с ним объекту, например
class Book(models.Model):
author = models.ForeignKey(Author)
name = models.ForeignKey(Region)
class Author(models.Model):
name = models.ForeignKey(Region)
Запрос
Author.objects.filter(book_name='name1',book_name='name2')
возвращает пустой набор
и запросить
Author.objects.filter(book_name='name1').filter(book_name='name2')
возвращает авторов, имеющих книги с именами "name1" и "name2"
Подробнее см. https://docs.djangoproject.com/en/dev/topics/db/queries/#s-spanning-multi-valued-relationships