Objects all не работает

Содержание
  1. .objects.all() не работает в Django
  2. Работа с запросами¶
  3. Создание объектов¶
  4. Сохранение изменений в объектах¶
  5. Сохранение полей ForeignKey и ManyToManyField ¶
  6. Получение объектов¶
  7. Получение всех объектов¶
  8. Получение определенных объектов с помощью фильтров¶
  9. Цепочки фильтров¶
  10. Отфильтрованные QuerySet являются уникальными¶
  11. « QuerySet« — ленивые¶
  12. Получение одного объекта с помощью get() ¶
  13. Другие методы QuerySet ¶
  14. Ограничение QuerySet ¶
  15. Поиск по полям¶
  16. Поиск, который использует отношения¶
  17. Охватывающие многозначные отношения¶
  18. Фильтры могут ссылаться на поля модели¶
  19. Использование сокращения pk ¶
  20. Экранирующие знаки процента и подчеркивания в выражениях LIKE ¶
  21. Кэширование и QuerySet ¶
  22. Когда QuerySet не кэшируется¶
  23. Запросы к JSONField ¶
  24. Хранение и запрос для « None«¶
  25. Преобразование ключа, индекса и пути¶
  26. Сдерживание и ключевые поиски¶
  27. contains ¶
  28. contained_by ¶
  29. has_key ¶
  30. has_keys ¶
  31. has_any_keys ¶
  32. Сложные поиски с объектами Q ¶
  33. Сравнение объектов¶
  34. Удаление объектов¶
  35. Копирование экземпляров модели¶
  36. Обновление нескольких объектов одновременно¶
  37. Связанные объекты¶
  38. Отношения один ко многим¶
  39. Прямые¶
  40. Обратные отношения¶
  41. Использование собственного реверсивного менеджера¶
  42. Дополнительные методы для обработки связанных объектов¶
  43. Отношения многие ко многим¶
  44. Отношения один-к-одному¶
  45. Как возможны обратные отношения?¶
  46. Запросы к связанным объектам¶
  47. Откат к сырому SQL¶

.objects.all() не работает в Django

Я разрабатываю сайт, основанный на информации о книгах, и я хочу отобразить всех авторов, присутствующих в таблице «Авторы» на странице HTML. Когда я нажимаю ссылку «авторы», страница не отображается, и появляется сообщение «Пользовательский запрос не существует». (Не позволяя мне размещать изображение здесь). Это трассировка с терминала.

Я попробовал выполнить запрос в python manage.py shell и дал правильный набор запросов.

Мой файл urls.py :

Функция «Мой вид»:

Моя страница html authors.html:

Функция просмотра «follow_user» предназначена только для записи в базу данных, у нее нет связанной с ней HTML-страницы.

Я посетил разные ссылки на подобные вопросы, но ни одна из них не решает мою проблему. link1: objects.all () query not working link2: Django objects.all() пустой набор запросов, а не пустой в оболочке

Помощь очень ценится. Спасибо

Ваш запрос /books/authors/ обрабатывается представлением follow_user , потому что оба они совпадают, а шаблон follow_user находится выше шаблона authors .

Вы можете исправить это, изменив регулярные выражения так, чтобы они не столкнулись, или, перемещая шаблон authors над шаблоном follow_user (обратите внимание, что это перестанет следовать за пользователем с username=’authors’ ).

После исправления ваших шаблонов URL трассировка подсказывает, что в вашем представлении follow_user есть проблема, которую вы должны исправить:

Если есть вероятность, что пользователь не существует в базе данных, вам также понадобится обработать эту возможность. Вы можете поймать исключение:

Или, возможно, вы можете использовать ярлык get_object_or_404 :

Наконец, обратите внимание, что следующая проверка неверна:

Источник

Работа с запросами¶

После того как вы создали модели данных , Django автоматически предоставляет вам API-интерфейс для базы данных, который позволяет создавать, извлекать, обновлять и удалять объекты. Этот документ объясняет, как использовать этот API. Обратитесь к справочнику по модели данных для получения полной информации обо всех различных параметрах поиска модели.

В этом руководстве (и в справочнике) мы будем ссылаться на следующие модели, которые составляют приложение Weblog:

Создание объектов¶

Для представления данных таблицы базы данных в объектах Python Django использует интуитивно понятную систему: класс модели представляет таблицу базы данных, а экземпляр этого класса представляет конкретную запись в таблице базы данных.

Чтобы создать объект, создайте его экземпляр с помощью аргументов ключевого слова для класса модели, а затем вызовите save() , чтобы сохранить его в базе данных.

Предполагая, что модели находятся в файле mysite/blog/models.py :

За кулисами выполняется SQL-оператор INSERT . Django не обращается в базу данных, пока вы не вызовете явно save() .

Метод save() не имеет возвращаемого значения.

save() использует несколько дополнительных параметров, которые здесь не описаны. Смотрите документацию save() для получения полной информации.

Чтобы создать и сохранить объект за один шаг, используйте метод create() .

Сохранение изменений в объектах¶

Чтобы сохранить изменения в объекте, который уже находится в базе данных, используйте save() .

Для экземпляра Blog b5 , который уже был сохранен в базе данных, этот пример меняет имя и обновляет запись в базе данных:

Здесь выполняется оператор SQL UPDATE . Django не делает запрос в базу данных, пока вы не вызовете явно save() .

Сохранение полей ForeignKey и ManyToManyField ¶

Обновление поля ForeignKey работает точно так же, как и сохранение обычного поля — назначьте объект нужного типа соответствующему полю. В этом примере обновляется атрибут blog экземпляра Entry entry , при условии, что соответствующие экземпляры Entry и Blog уже сохранены в базе данных (поэтому мы можем получить их ниже):

Обновление ManyToManyField работает немного иначе — используйте метод add() для добавления записи к отношению. Этот пример добавляет экземпляр Author joe к объекту entry :

Чтобы добавить несколько записей в ManyToManyField за один раз, включите в вызов несколько аргументов add() , например:

Джанго сообщит, если вы попытаетесь назначить или добавить объект неправильного типа.

Получение объектов¶

Чтобы получить объекты из вашей базы данных, создайте QuerySet через Manager в своем классе модели.

QuerySet представляет коллекцию объектов из вашей базы данных. Может иметь ноль, один или несколько фильтров. Фильтры сужают результаты запроса на основе заданных параметров. В терминах SQL QuerySet приравнивается к оператору SELECT , а фильтр является ограничивающим предложением, таким как WHERE или LIMIT .

Вы получаете QuerySet , используя класс менеджер Manager вашей модели. Каждая модель имеет по крайней мере один Manager , и по умолчанию он называется objects . Доступ к нему напрямую через класс модели, например:

Managers доступны только через классы модели, а не из экземпляров модели, чтобы обеспечить разделение между операциями на уровне таблицы и операциями на уровне записи.

Manager является основным источником QuerySets для модели. Например, Blog.objects.all() возвращает QuerySet , который содержит все объекты Blog в базе данных.

Получение всех объектов¶

Самый простой способ извлечь объекты из таблицы — это получить их все. Для этого используйте метод all() в классе Manager :

Метод all() возвращает QuerySet всех объектов в базе данных.

Получение определенных объектов с помощью фильтров¶

QuerySet , возвращаемый all() описывает все объекты в таблице базы данных. Обычно нужно выбрать только подмножество полного набора объектов.

Чтобы создать такое подмножество, вы уточняете исходный QuerySet , добавляя условия фильтра. Два наиболее распространенных способа уточнить QuerySet :

filter(**kwargs) Возвращает новый QuerySet , содержащий объекты, которые соответствуют заданным параметрам поиска. exclude(**kwargs) Возвращает новый QuerySet , содержащий объекты, которые не соответствуют указанным параметрам поиска.

Параметры поиска ( **kwargs в приведенных выше определениях функций) должны быть в формате, описанном в разделе Поиск по полю .

Например, чтобы получить QuerySet записей блога за 2006 год, используйте filter() примерно так:

С классом менеджера по умолчанию, он такой же, как:

Цепочки фильтров¶

Результат уточнения QuerySet сам по себе является QuerySet , поэтому можно объединять уточнения вместе. Например:

Здесь берется начальный QuerySet всех записей в базе данных, добавляется фильтр, затем исключение, затем другой фильтр. Окончательный результат QuerySet , содержащий все записи с заголовком, начинающимся с «What», которые были опубликованы в период с 30 января 2005 года и по сегодняшний день.

Отфильтрованные QuerySet являются уникальными¶

Каждый раз, когда вы уточняете QuerySet , вы получаете совершенно новый QuerySet , который никак не связан с предыдущим QuerySet . Каждое уточнение создает отдельный QuerySet , который можно хранить, использовать и переиспользовать повторно.

Эти три QuerySets — разные. Первый — это базовый QuerySet , содержащий все записи, содержащие заголовок, начинающийся с «What». Второе — это подмножество первого, с дополнительными критериями, исключающими записи, чье pub_date сегодня или в будущем. Третий — это подмножество первого, с дополнительными критериями, которые выбирают только те записи, чьи pub_date находятся сегодня или в будущем. Начальный QuerySet ( q1 ) не зависит от процесса уточнения.

« QuerySet« — ленивые¶

QuerySets ленивые — процесс создания QuerySet не связан с какими-либо действиями с базой данных. Вы можете складывать фильтры вместе весь день, и Django не будет выполнять запрос до тех пор, пока не будет вызван QuerySet . Посмотрите на этот пример:

Хотя это выглядит как три запроса в базу данных, на самом деле это только один запрос в базу данных, в последней строке ( print(q) ). В общем, результаты QuerySet не извлекаются из базы данных, пока вы не запросите их. Когда вы это делаете, QuerySet вызывается путем доступа к базе данных. Для получения более подробной информации о том, когда именно происходит вызов, смотрите Когда вычисляется QuerySet .

Получение одного объекта с помощью get() ¶

filter() всегда возвращает QuerySet , даже если только один объект соответствует запросу — в этом случае это будет QuerySet , содержащий один элемент.

Если вы знаете, что только один объект соответствует вашему запросу, вы можете использовать метод get() из Manager который возвращает объект напрямую:

Вы можете использовать любое выражение запроса с get() , так же как с filter() . Смотрите Поиск по полю .

Обратите внимание, что есть разница между использованием get() и использованием filter() с фрагментом [0] . Если нет результатов, соответствующих запросу, то get() вызовет исключение DoesNotExist . Это исключение является атрибутом класса модели, к которому выполняется запрос — поэтому в приведенном выше коде, если нет объекта Entry с первичным ключом 1, Django вызовет Entry.DoesNotExist .

Точно так же Django выдаст ошибку, если более чем один элемент соответствует запросу get() . В этом случае он вызовет MultipleObjectsReturned , который тоже является атрибутом самого класса модели.

Другие методы QuerySet ¶

В большинстве случаев вы будете использовать all() , get() , filter() и exclude() , когда вам нужно искать объекты в базе данных. Однако это далеко не все; смотрите Справочник по API QuerySet для получения полного списка всех методов QuerySet .

Ограничение QuerySet ¶

Используйте подмножество синтаксиса нарезки массивов в Python, чтобы ограничить ваш QuerySet определенным количеством результатов. Это эквивалент выражений SQL LIMIT и OFFSET .

Читайте также:  Приложение megogo для smart tv не работает

Например, этот код возвращает первые 5 объектов ( LIMIT 5 ):

Это возвращает объекты с шестого по десятый ( OFFSET 5 LIMIT 5 ):

Отрицательное индексирование (т.е. Entry.objects.all()[-1] ) не поддерживается.

Как правило, такая выборка QuerySet возвращает новый QuerySet — он не вызывает запрос. Исключением является использование параметра «step» синтаксиса фрагмента Python. Например, этот код фактически выполнит запрос, чтобы вернуть список каждого второго объекта из первых 10:

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

Чтобы извлечь один объект, а не список (например, SELECT foo FROM bar LIMIT 1 ), используйте простой индекс вместо среза. Например, этот код возвращает первый Entry в базе данных, после упорядочивания записей в алфавитном порядке по заголовку:

Это примерно эквивалентно:

Однако обратите внимание, что первый из них вызовет IndexError , а второй вызовет DoesNotExist , если ни один объект не соответствует заданным критериям. Смотрите get() для получения более подробной информации.

Поиск по полям¶

Поиск по полю — это то, как вы определяете содержание выражения SQL WHERE . Они указываются в качестве аргументов ключевых слов для методов filter() , exclude() и get() класса QuerySet .

Базовые аргументы поиска по ключевым словам имеют вид field__lookuptype=value . (Это двойное подчеркивание). Например:

переводит (примерно) в следующий SQL:

Как это возможно

Python имеет возможность определять функции, которые принимают произвольные аргументы имя-значение, имена и значения которых оцениваются во время выполнения. Для получения дополнительной информации см. Keyword Arguments в официальном руководстве по Python.

Поле, указанное в поиске, должно быть именем поля модели. Однако есть одно исключение: в случае ForeignKey вы можете указать имя поля с суффиксом _id . В этом случае ожидается, что параметр value будет содержать необработанное значение первичного ключа внешней модели. Например:

Если вы передадите неверный аргумент ключевого слова, функция поиска вызовет TypeError .

API базы данных поддерживает около двух десятков типов поиска; полная документация может быть найдена в справочнике поиска по полям . Чтобы дать вам представление о том, что доступно, вот некоторые из наиболее часто используемых поисков:

«Точное» совпадение. Например:

Будет генерировать SQL по этим строкам:

Если вы не предоставляете тип поиска — то есть, если аргумент ключевого слова не содержит двойного подчеркивания, — тип поиска считается точным .

Например, следующие два оператора эквивалентны:

Это сделано для удобства, потому что точный поиск является распространенным случаем.

Соответствие без учета регистра. Итак, запрос:

Будет соответствовать Blog с названием «Beatles Blog» , «beatles blog» или даже «BeAtlES blOG» .

Проверка содержимого в зависимости от регистра. Например:

Примерно переводится в такой SQL:

Обратите внимание, что это будет соответствовать заголовку ‘Today Lennon honored’ , но не ‘today lennon honored’ .

Существует также версия без учета регистра icontains .

startswith , endswith «Начинается с» и «заканчивается» соответственно. Существуют также версии без учета регистра istartswith и iendswith .

Опять же, это только поверхностное описание. Полное руководство можно найти в Справочнике поиска по полям .

Поиск, который использует отношения¶

Django предлагает мощный и интуитивно понятный способ «отслеживать» отношения в поисках, автоматически заботясь о SQL JOIN для вас, за кулисами. Чтобы охватить отношение, просто используйте имя поля связанных полей в моделях, разделенных двойным подчеркиванием, пока не дойдете до нужного поля.

В этом примере извлекаются все объекты Entry с помощью Blog , чье name равно ‘Beatles Blog’ :

Этот охват может быть настолько глубоким, насколько вы захотите.

Это работает и в обратном направлении. Хотя это можно настроить , по умолчанию вы обращаетесь к «обратному» отношению в поиске, используя имя модели в нижнем регистре.

В этом примере извлекаются все объекты Blog , у которых есть хотя бы один Entry , чей headline содержит ‘Lennon’ :

Если вы фильтруете по нескольким отношениям и одна из промежуточных моделей не имеет значения, которое удовлетворяет условию фильтра, Django будет обрабатывать его как пустой (все значения NULL ), но допустимый объект там. Все это означает, что никакой ошибки не возникнет. Например, в этом фильтре:

(если была связанная Author модель), если бы не было author , связанного с записью, она будет обрабатываться так, как если бы к ней также не было прикреплено name , вместо того, чтобы выдавать ошибку из-за пропавшего author . Обычно это именно то, что вы хотите, чтобы произошло. Единственный случай, когда это может сбить с толку, это если вы используете isnull . Таким образом:

вернет объекты Blog , которые имеют пустое name в author , а также те, которые имеют пустое author в entry . Если вы не хотите получать эти последние объекты, вы можете написать:

Охватывающие многозначные отношения¶

Когда вы фильтруете объект на основе ManyToManyField или обратного ForeignKey , вас могут заинтересовать два вида фильтров. Рассмотрим отношение Blog / Entry (отношение Blog к Entry является отношением один ко многим). Мы могли бы заинтересоваться поиском блогов, в которых есть запись с заголовком «Lennon» и которая была опубликована в 2008 году. Или мы могли бы также найти блоги, в которых есть запись с заголовком «Lennon» в заголовке как запись, которая была опубликована в 2008 году. Поскольку существует несколько записей, связанных с одним Blog , оба эти запроса возможны и имеют смысл в некоторых ситуациях.

Ситуация такого же типа возникает с ManyToManyField . Например, если Entry имеет ManyToManyField , называемый tags , мы можем захотеть найти записи, связанные с тегами «music» и «band» или нам может потребоваться запись, которая содержит тег с именем «music» и статусом «public».

Чтобы справиться с обеими этими ситуациями, Django имеет согласованный способ обработки filter() . Все внутри одного вызова filter() применяется одновременно, чтобы отфильтровать элементы, соответствующие всем этим требованиям. Последовательные вызовы filter() дополнительно ограничивают набор объектов, но для многозначных отношений они применяются к любому объекту, связанному с первичной моделью, не обязательно к тем объектам, которые были выбранный ранее вызовом filter() .

Это может показаться немного запутанным, поэтому, надеемся, пример прояснит. Чтобы выбрать все блоги, которые содержат записи с «Lennon» в заголовке и которые были опубликованы в 2008 году (та же запись, удовлетворяющая обоим условиям), мы должны написать:

Чтобы выбрать все блоги, которые содержат запись с «Lennon» в заголовке, а также запись, которая была опубликована в 2008 году, мы должны написать:

Предположим, что существует только один блог, в котором есть записи, содержащие «Lennon» и записи 2008 года, но ни одна из записей 2008 года не содержит «Lennon». Первый запрос не вернет ни одного блога, но второй запрос вернет этот блог.

Во втором примере первый фильтр ограничивает набор запросов всеми теми блогами, которые связаны с записями с «Lennon» в заголовке. Второй фильтр ограничивает набор блогов далее теми, которые также связаны с записями, опубликованными в 2008 году. Записи, выбранные вторым фильтром, могут совпадать или не совпадать с записями в первом фильтре. Мы фильтруем элементы Blog с каждым оператором фильтра, а не элементы Entry .

Поведение filter() для запросов, которые охватывают многозначные отношения, как описано выше, не реализовано эквивалентно для exclude() . Вместо этого условия в одном вызове exclude() не обязательно ссылаются на один и тот же элемент.

Например, следующий запрос исключит блоги, содержащие обе записи с «Lennon» в заголовке и записи, опубликованные в 2008 году:

Однако, в отличие от поведения при использовании filter() , это не ограничивает блоги на основе записей, которые удовлетворяют обоим условиям. Чтобы сделать это, то есть, чтобы выбрать все блоги, которые не содержат записей, опубликованных с «Lennon», которые были опубликованы в 2008 году, вам нужно сделать два запроса:

Фильтры могут ссылаться на поля модели¶

В приведенных выше примерах мы создали фильтры, которые сравнивают значение модельного поля с константой. Но что, если вы хотите сравнить значение поля модели с другим полем той же модели?

Django предоставляет F выражения , чтобы разрешить такие сравнения. Экземпляры F() действуют как ссылка на поле модели в запросе. Затем эти ссылки можно использовать в фильтрах запросов для сравнения значений двух разных полей в одном экземпляре модели.

Например, чтобы найти список всех записей блога, у которых было больше комментариев, чем у пингбэков, мы создаем объект F() для ссылки на счетчик пингбэков и используем этот объект F() в запросе:

Django поддерживает использование сложения, вычитания, умножения, деления, модуля и степеней с объектами F() , как с константами, так и с другими объектами F() . Чтобы найти все записи в блоге с более чем вдвое большим количеством комментариев, чем пингбэками, мы модифицируем запрос:

Чтобы найти все записи, в которых рейтинг записи меньше суммы пингбэков и комментариев, мы должны выполнить запрос:

Вы также можете использовать нотацию двойного подчеркивания, чтобы охватить отношения в объекте F() . Объект F() с двойным подчеркиванием будет вводить любые объединения, необходимые для доступа к связанному объекту. Например, чтобы получить все записи, в которых имя автора совпадает с именем блога, мы можем выполнить запрос:

Для полей даты и даты/времени вы можете добавить или вычесть объект timedelta . Следующее вернет все записи, которые были изменены более чем через 3 дня после их публикации:

Объекты F() поддерживают побитовые операции с помощью .bitand() , .bitor() , .bitxor() , .bitrightshift() и .bitleftshift() . Например:

Oracle не поддерживает побитовую операцию XOR.

Добавлена поддержка .bitxor() .

Использование сокращения pk ¶

Для удобства Django предоставляет сокращение для поиска pk , который обозначает «первичный ключ».

В примере модели Blog первичным ключом является поле id , поэтому эти три оператора эквивалентны:

Использование pk не ограничивается __exact запросами — любое условие запроса может быть объединено с pk для выполнения запроса по первичному ключу модели:

Поиск pk также работает через объединения. Например, эти три утверждения эквивалентны:

Читайте также:  После замены жесткого диска не работает принтер

Экранирующие знаки процента и подчеркивания в выражениях LIKE ¶

Поиск в полях, эквивалентный операторам LIKE ( iexact , contains , icontains , startswith , istartswith , endswith and iendswith ) автоматически уберет два специальных символа, используемых в операторах LIKE — знак процента и подчеркивание. (В операторе LIKE знак процента означает подстановочный знак из нескольких символов, а подчеркивание означает подстановочный знак из одного символа.)

Это означает, что все должно работать интуитивно, чтобы абстракция не просачивалась. Например, чтобы получить все записи, содержащие знак процента, просто используйте знак процента, как и любой другой символ:

Джанго заботится об экранировании для вас; результирующий SQL будет выглядеть примерно так:

То же самое касается подчеркивания. Оба знака процента и подчеркивания обрабатываются для вас прозрачно.

Кэширование и QuerySet ¶

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

Во вновь созданном QuerySet кеш пуст. Первый раз QuerySet оценивается и, следовательно, происходит запрос к базе данных — Django сохраняет результаты запроса QuerySet в кэш и возвращает результаты, которые были явно запрошены (например, следующий элемент, если итерация происходит через QuerySet ). Последующие оценки QuerySet повторно используют кэшированные результаты.

Помните об этом поведении кэширования, потому что оно может удивить вас, если вы не используете правильно QuerySet . Например, следующее создаст два QuerySet , оцените их:

Это означает, что один и тот же запрос к базе данных будет выполнен дважды, что фактически удваивает нагрузку на вашу базу данных. Кроме того, существует вероятность того, что два списка могут не включать в себя одни и те же записи базы данных, потому что «запись» может быть добавлена или удалена за доли секунды между двумя запросами.

Чтобы избежать этой проблемы, просто сохраните QuerySet и повторно используйте его:

Когда QuerySet не кэшируется¶

Queryset`ы не всегда кэшируют свои результаты. При оценке только части набора запросов проверяется кэш, но если он не заполняется, элементы, возвращаемые последующим запросом, не кэшируются. В частности, это означает, что ограничение набора запросов с использованием среза массива или индекса не заполнит кэш.

Например, многократное получение определенного индекса в объекте набора запросов будет каждый раз запрашивать базу данных:

Однако, если весь набор запросов уже был оценен, вместо этого будет проверяться кеш:

Вот несколько примеров других действий, которые приведут к оценке всего набора запросов и, следовательно, заполнению кеша:

Простой вывод набора запросов не заполнит кэш. Это связано с тем, что вызов __repr__() возвращает только часть всего набора запросов.

Запросы к JSONField ¶

Реализация поисков отличается в JSONField , главным образом из-за существования ключевых преобразований. Для демонстрации мы будем использовать следующий пример модели:

Хранение и запрос для « None«¶

Как и в случае других полей, сохранение None в качестве значения поля сохранит его как SQL NULL . Хотя это не рекомендуется, можно хранить скаляр JSON null вместо SQL NULL , используя Value(‘null’) .

Независимо от того, какие значения сохранены, при извлечении из базы данных представление Python скалярного JSON null совпадает с SQL NULL , т.е. None . Поэтому может быть трудно различить их.

Это относится только к None как значению верхнего уровня поля. Если None находится внутри list или dict , он всегда будет интерпретироваться как JSON null .

При запросе значение None всегда будет интерпретироваться как JSON null . Чтобы запросить SQL NULL , используйте isnull :

Если вы не уверены, что хотите работать со значениями SQL NULL , рассмотрите возможность установки null=False и обеспечения подходящего значения по умолчанию для пустых значений, например default=dict .

Хранение JSON скаляра null не нарушает null=False .

Преобразование ключа, индекса и пути¶

Для запроса на основе заданного ключа словаря используйте этот ключ в качестве имени поиска:

Несколько ключей могут быть объединены в цепочку для формирования пути поиска:

Если ключ является целым числом, он будет интерпретирован как преобразование индекса в массиве:

Если ключ, который вы хотите запросить, конфликтует с именем другого поиска, используйте вместо этого поиск contains .

Чтобы запросить отсутствующие ключи, используйте поиск isnull :

В приведенных выше примерах поиска неявно используется поиск exact . Преобразования ключей, индекса и пути также могут быть связаны с: icontains , endswith , iendswith , iexact , regex , iregex , startswith , istartswith , lt , lte , gt , и gte , также как с Сдерживание и ключевые поиски .

Из-за способа работы запросов по ключевым путям exclude() и filter() не гарантируются производить исчерпывающие наборы. Если вы хотите включить объекты, у которых нет пути, добавьте поиск isnull .

Поскольку любая строка может быть ключом в объекте JSON, любой поиск, кроме перечисленных ниже, будет интерпретироваться как поиск ключа. Ошибок не возникает. Будьте особенно осторожны с опечатками и всегда проверяйте, работают ли ваши запросы так, как вы хотите.

Пользователи MariaDB и Oracle

Использование order_by() для преобразований ключа, индекса или пути отсортирует объекты с использованием строкового представления значений. Это связано с тем, что MariaDB и Oracle Database не предоставляют функцию, которая преобразует значения JSON в их эквивалентные значения SQL.

В Oracle Database использование None в качестве значения для поиска в запросе exclude() вернет объекты, которые не имеют null в качестве значения в заданный путь, включая объекты, которые не имеют пути. На других серверах базы данных запрос будет возвращать объекты, которые имеют путь, и значение не равно null .

В PostgreSQL, если используется только один ключ или индекс, используется оператор SQL -> . Если используется несколько операторов, то используется оператор #> .

Сдерживание и ключевые поиски¶

contains ¶

Поиск contains переопределяется в JSONField . Возвращаемые объекты — это те, в которых заданный dict пар ключ-значение содержится в верхнем уровне поля. Например:

Oracle и SQLite

contains не поддерживается в Oracle и SQLite.

contained_by ¶

Это обратное значение contains — возвращаемые объекты будут теми, где пары ключ-значение на объекте являются подмножеством пар в переданном значении. Например:

Oracle и SQLite

contains_by не поддерживается в Oracle и SQLite.

has_key ¶

Возвращает объекты, в которых данный ключ находится на верхнем уровне данных. Например:

has_keys ¶

Возвращает объекты, в которых все данные ключи находятся на верхнем уровне данных. Например:

has_any_keys ¶

Возвращает объекты, где любой из указанных ключей находится на верхнем уровне данных. Например:

Сложные поиски с объектами Q ¶

Запросы ключевых аргументов в filter() и т.д. — объединяются вместе «AND». Если вам нужно выполнить более сложные запросы (например, запросы с помощью операторов OR ), вы можете использовать Q объекты .

Q объект ( django.db.models.Q ) — это объект, используемый для инкапсуляции набора ключевых аргументов. Эти ключевые аргументы указаны также как и в «Поиск по полям» выше.

Например, этот объект Q инкапсулирует один запрос LIKE :

Объекты Q можно комбинировать с помощью операторов & и | . Когда оператор используется с двумя объектами Q , он создает новый объект Q .

Например, этот оператор выдает один объект Q , который представляет «OR» двух запросов «question__startswith» :

Это эквивалентно следующему оператору SQL WHERE :

Вы можете составлять операторы произвольной сложности, комбинируя объекты Q с операторами & и | и используя группировку в скобках. Кроме того, объекты Q могут быть отменены с помощью оператора

, что позволяет комбинировать поиск, который объединяет как обычный запрос, так и отрицательный ( NOT ) запрос:

Каждая функция поиска, которая принимает ключевые слова-аргументы (например filter() , exclude() , get() ) также может быть передан один или несколько объектов Q в качестве позиционных (неименованных) аргументов. Если вы предоставляете несколько аргументов объекта Q для функции поиска, аргументы будут объединены «AND». Например:

… примерно переводится в SQL как:

Функции поиска могут смешивать использование Q объектов и ключевых аргументов. Все аргументы, предоставляемые функции поиска (будь то аргументы с ключевыми словами или объекты Q ), соединяются «AND». Однако, если предоставляется объект Q , он должен предшествовать определению любых аргументов ключевого слова. Например:

… будет правильным запросом, эквивалентным предыдущему примеру, но:

… не будет верным.

примеры поиска с OR в модульных тестах Django показывают некоторые возможные варианты использования Q .

Сравнение объектов¶

Чтобы сравнить два экземпляра модели, просто используйте стандартный оператор сравнения Python, знак двойного равенства: == . За кулисами сравниваются значения первичных ключей двух моделей.

Используя приведенный выше пример Entry , следующие два оператора эквивалентны:

Если первичный ключ модели не называется id , нет проблем. Сравнения всегда будут использовать первичный ключ, как бы он ни назывался. Например, если поле первичного ключа модели называется name , эти два оператора эквивалентны:

Удаление объектов¶

The delete method, conveniently, is named delete() . This method immediately deletes the object and returns the number of objects deleted and a dictionary with the number of deletions per object type. Example:

Вы также можете удалить объекты массово. Каждый метод QuerySet имеет метод delete() , который удаляет все элементы этого класса QuerySet .

Например, это удаляет все объекты Entry с pub_date 2005 года:

Имейте в виду, что это, когда это возможно, будет выполняться исключительно в SQL, и поэтому методы delete() отдельных экземпляров объекта не обязательно будут вызываться во время процесса. Если вы предоставили пользовательский метод delete() для класса модели и хотите убедиться, что он вызывается, вам нужно будет «вручную» удалить экземпляры этой модели (например, путем итерации по QuerySet и вызывать delete() для каждого объекта в отдельности), а не с использованием метода массового delete() класса QuerySet .

Когда Django удаляет объект, по умолчанию он эмулирует поведение ограничения SQL ON DELETE CASCADE — другими словами, любые объекты, имеющие внешние ключи, указывающие на объект, который будет удален, будут удалены вместе с ним. Например:

Это каскадное поведение настраивается с помощью аргумента on_delete для ForeignKey .

Обратите внимание, что delete() является единственным методом QuerySet , который не предоставляется классу Manager сам. Это механизм безопасности, который предотвращает случайный запрос Entry.objects.delete() и удаление всех записей. Если вы хотите хотите удалить все объекты, вам нужно явно запросить полный набор запросов:

Читайте также:  Скроллинг ноутбук не работает

Копирование экземпляров модели¶

Хотя нет встроенного метода для копирования экземпляров модели, можно легко создать новый экземпляр со скопированными значениями всех полей. В простейшем случае вы можете просто установить pk в None . Используя наш пример блога:

Все становится сложнее, если вы используете наследование. Рассмотрим подкласс Blog :

Из-за того, как работает наследование, вы должны установить для pk и id значение None :

Этот процесс не копирует отношения, которые не являются частью таблицы базы данных модели. Например, Entry имеет ManyToManyField для Author . После дублирования записи вы должны установить отношения «многие ко многим» для новой записи:

Для OneToOneField вы должны продублировать связанный объект и назначить его полю нового объекта, чтобы избежать нарушения однозначного уникального ограничения. Например, предполагая, что entry уже продублировано, как указано выше:

Обновление нескольких объектов одновременно¶

Иногда вы хотите установить для поля определенное значение для всех объектов в QuerySet . Вы можете сделать это с помощью метода update() . Например:

Используя этот метод, вы можете устанавливать только нереляционные поля и поля ForeignKey . Чтобы обновить нереляционное поле, укажите новое значение как константу. Чтобы обновить ForeignKey поля, установите новое значение в качестве нового экземпляра модели, на который вы хотите указать. Например:

Метод update() применяется мгновенно и возвращает количество строк, соответствующих запросу (которое может быть не равно количеству обновленных строк, если некоторые строки уже имеют новое значение). Единственное ограничение на обновляемый QuerySet состоит в том, что он может получить доступ только к одной таблице базы данных: главной таблице модели. Вы можете фильтровать на основе связанных полей, но вы можете обновить только столбцы в основной таблице модели. Пример:

Помните, что метод update() преобразуется непосредственно в оператор SQL. Это массовая операция для прямых обновлений. Он не запускает какие-либо методы save() на ваших моделях или сигналы pre_save или post_save (которые являются следствием вызова save() ), и не обновляет поля auto_now . Если вы хотите сохранить каждый элемент в QuerySet и убедиться, что метод save() вызывается в каждом экземпляре Вам не нужны никакие специальные функции для этого. Просто зациклите их и вызовите save() :

Вызовы обновлений также могут использовать выражения F для обновления одного поля на основе значения другого поля в модели. Это особенно полезно для увеличения счетчиков на основе их текущего значения. Например, чтобы увеличить количество пингбэков для каждой записи в блоге:

Однако, в отличие от объектов F() в filter и exclude, вы не можете вводить объединения при использовании объектов F() в обновлении — вы можете ссылаться только на поля, локальные для обновляемой модели. Если вы попытаетесь ввести объединение с объектом F() , будет вызвано FieldError :

Связанные объекты¶

Когда вы определяете отношение в модели (то есть ForeignKey , OneToOneField , или ManyToManyField ), экземпляры этой модели будут иметь удобный API для доступа к связанным объектам.

Используя модели в верхней части этой страницы, например, объект Entry e может получить связанный с ним объект Blog , обратившись к атрибуту blog : e.blog .

(За кулисами эта функциональность реализована с помощью дескрипторов Python. Это не должно иметь большого значения для вас, но мы отметим это здесь для любопытных.)

Django также создает средства доступа API для «другой» стороны отношения — ссылки из связанной модели на модель, которая определяет отношение. Например, объект Blog b имеет доступ к списку всех связанных объектов Entry через атрибут entry_set : b.entry_set.all() .

Все примеры в этом разделе используют образцы моделей Blog , Author и Entry , определенные в начале этой страницы.

Отношения один ко многим¶

Прямые¶

Если модель имеет ForeignKey , экземпляры этой модели будут иметь доступ к связанному (чужому) объекту через простой атрибут модели.

Вы можете получить и установить через атрибут внешнего ключа. Как вы можете ожидать, изменения во внешнем ключе не сохраняются в базе данных, пока вы не вызовете save() . Пример:

Если поле ForeignKey установлено null=True (т.е. оно допускает значения NULL ), вы можете назначить None для удаления отношения. Пример:

Прямой доступ к отношениям «один ко многим» кэшируется при первом обращении к связанному объекту. Последующие обращения к внешнему ключу в том же экземпляре объекта кэшируются. Пример:

Обратите внимание, что select_related() QuerySet рекурсивно предварительно заполняет кэш всех отношений «один ко многим» . Пример:

Обратные отношения¶

Если модель имеет ForeignKey , экземпляры модели внешнего ключа будут иметь доступ к Manager , который возвращает все экземпляры первой модели. По умолчанию этот Manager называется FOO_set , где FOO — имя исходной модели в нижнем регистре. Этот Manager возвращает QuerySets , который можно фильтровать и манипулировать, как описано в разделе «Получение объектов» выше.

Вы можете переопределить имя FOO_set , установив параметр related_name в определении ForeignKey . Например, если модель Entry была изменена на blog = ForeignKey(Blog, on_delete=models.CASCADE, related_name=’records’) , приведенный выше пример кода будет выглядеть следующим образом:

Использование собственного реверсивного менеджера¶

По умолчанию RelatedManager , используемый для обратных отношений, является подклассом менеджер по умолчанию для этой модели. Если вы хотите указать другой менеджер для данного запроса, вы можете использовать следующий синтаксис:

Если EntryManager выполняет фильтрацию по умолчанию в своем методе get_queryset() , эта фильтрация будет применяться к вызову all() .

Указание собственного обратного менеджера также позволяет вам вызывать его пользовательские методы:

Дополнительные методы для обработки связанных объектов¶

В дополнение к методам QuerySet , определенным выше в разделе «Извлечение объектов», ForeignKey Manager имеет дополнительные методы, используемые для обработки набора связанных объектов. Ниже приведен краткий обзор каждого из них, а подробности можно найти в справочник связанных объектов .

add(obj1, obj2, . ) Добавляет указанные объекты модели в набор связанных объектов. create(**kwargs) Создает новый объект, сохраняет его и помещает в набор связанных объектов. Возвращает вновь созданный объект. remove(obj1, obj2, . ) Удаляет указанные объекты модели из набора связанных объектов. clear() Удаляет все объекты из набора связанных объектов. set(objs) Заменяет набор связанных объектов.

Чтобы назначить членов связанного набора, используйте метод set() с повторяющимися экземплярами объекта. Например, если e1 и e2 являются экземпляром Entry :

Если доступен метод clear() , все ранее существующие объекты будут удалены из entry_set , прежде чем все объекты в итерируемом объекте (в данном случае список) будут добавлены в набор. Если метод clear() недоступен, все объекты в итерируемых будут добавлены без удаления каких-либо существующих элементов.

Каждая «обратная» операция, описанная в этом разделе, оказывает непосредственное влияние на базу данных. Каждое добавление, создание и удаление немедленно и автоматически сохраняется в базе данных.

Отношения многие ко многим¶

Обе стороны отношения «многие ко многим» получают автоматический доступ API другой стороны. API работает аналогично «обратному» отношению «один ко многим» выше.

Одно из различий заключается в именовании атрибутов: модель, которая определяет ManyToManyField , использует имя атрибута самого поля, тогда как «обратная» модель использует имя модели в нижнем регистре исходной модели, плюс ‘_set’ (точно так же, как обратные отношения один ко многим).

Пример облегчает понимание:

Например ForeignKey , ManyToManyField могут указывать related_name . В приведенном выше примере, если ManyToManyField в Entry указал related_name=’records’ , то каждый экземпляр Author будет иметь entries вместо entry_set .

Другое отличие от отношений один ко многим заключается в том, что в дополнение к экземплярам модели добавлены следующие методы: add() , set() и remove() . Например, если e1 и e2 являются экземплярами Entry , то эти вызовы set() работают одинаково:

Отношения один-к-одному¶

Отношения один-к-одному очень похожи на отношения многие-к-одному. Если вы определяете OneToOneField в вашей модели, экземпляры этой модели будут иметь доступ к связанному объекту через простой атрибут модели.

Разница заключается в «обратных» запросах. Связанная модель в отношении «один к одному» также имеет доступ к объекту Manager , но этот Manager представляет отдельный объект , а не набор объектов:

Если объекту не был присвоен объект, Django вызовет исключение DoesNotExist .

Экземпляры могут быть назначены на обратную связь так же, как вы бы назначили прямую связь:

Как возможны обратные отношения?¶

Другие объектно-реляционные связи требуют, чтобы вы определяли отношения с обеих сторон. Разработчики Django считают, что это является нарушением принципа DRY (не повторяй себя), поэтому Django требует, чтобы вы определяли отношения только с одной стороны.

Но как это возможно, учитывая, что класс модели не знает, какие другие классы модели связаны с ним, пока эти другие классы модели не будут загружены?

Ответ лежит в реестре приложений . Когда запускается Django, он импортирует каждое приложение, указанное в INSTALLED_APPS , а затем модуль models внутри каждого приложения. Всякий раз, когда создается новый класс моделей, Django добавляет обратные связи к любым связанным моделям. Если связанные модели еще не были импортированы, Django отслеживает отношения и добавляет их, когда связанные модели в конечном итоге импортируются.

По этой причине особенно важно, чтобы все используемые вами модели были определены в приложениях, перечисленных в INSTALLED_APPS . В противном случае обратные отношения могут не работать должным образом.

Запросы к связанным объектам¶

Запросы, связанные со связанными объектами, подчиняются тем же правилам, что и запросы, включающие поля с обычными значениями. При указании значения для сопоставляемого запроса вы можете использовать либо сам экземпляр объекта, либо значение первичного ключа для объекта.

Например, если у вас есть объект Blog b с id=5 , следующие три запроса будут идентичны:

Откат к сырому SQL¶

Если вам понадобится написать SQL-запрос, который слишком сложен для обработки базы данных Django, вы можете вернуться к написанию SQL вручную. У Django есть несколько вариантов написания необработанных SQL-запросов; смотрите Выполнение необработанных SQL-запросов .

Наконец, важно отметить, что уровень базы данных Django — это просто интерфейс к вашей базе данных. Вы можете получить доступ к вашей базе данных с помощью других инструментов, языков программирования или фреймворков баз данных; нет ничего специфичного для Django в вашей базе данных.

Источник

Оцените статью