|
Table of contents
|
Знание о том, как можно создавать и изменять данные достаточно, но есть вероятность, что ваше приложение будет гораздо чаще обращаться к существующим объектам, чем создавать новые. Мы уже знаем способ получения каждой записи определённой модели: >>> Publisher.objects.all() [<Publisher: Apress>, <Publisher: O'Reilly>]
В общих чертах в SQL это выглядит так: SELECT
id, name, address, city, state_province, country, website
FROM book_publisher;
ЗамечаниеСледует отметить, что Django не использует SELECT * при просмотре данных, а вместо этого явно перечисляет все поля. Так было задумано изначально: в некоторых случаях использование SELECT * может повлиять на производительность, а главное, перечисление полей более соответствует нормам Искусства программирования на языке Python: «Явное лучше неявного». Для получения более подробной информации об Искусстве программирования на языке Python выполните в консоли Python команду import this.
Теперь внимательно рассмотрим строку Publisher.objects.all():
Любая выборка из базы данных работает по определённому шаблону — мы используем методы менеджера, который подключен к модели, по которой производится выборка.
Естественно, что достаточно редко требуется получать
весь набор данных из модели
единовременно. В большинстве случаев нам требуется обработать
небольшую часть данных. Мы можем осуществить это с помощью
метода >>> Publisher.objects.filter(name='Apress') [<Publisher: Apress>]
Метод SELECT id, name, address, city, state_province, country, website FROM books_publisher WHERE name = 'Apress';
Вы можете передать множество аргументов в
>>> Publisher.objects.filter(country="U.S.A.", state_province="CA") [<Publisher: Apress>]
Множество аргументов будут объединены с помощью SQL операторов AND. Пример станет таким: SELECT id, name, address, city, state_province, country, website FROM books_publisher WHERE country = 'U.S.A.' AND state_province = 'CA';
Следует отметить, что по умолчанию выборка использует SQL оператор = для точного совпадения. Также можно выполнять другие виды запросов: >>> Publisher.objects.filter(name__contains="press") [<Publisher: Apress>]
Обратите внимание на двойное подчёркивание между name и contains. Подобно Python это используется Django для выполнения «магических» действий. В данном случае __contains преобразовывается в SQL оператор LIKE: SELECT id, name, address, city, state_province, country, website FROM books_publisher WHERE name LIKE '%press%';
Доступны множество типов выборок, включая icontains (независящий от регистра LIKE), startswith и endswith, а также range (SQL оператор BETWEEN). В приложении «Справочник по API взаимодействия с базой данных» подробно описаны все типы выборок.
Вышеприведённые примеры использования
>>> Publisher.objects.get(name="Apress") <Publisher: Apress>
Вместо списка (т.е., набора данных
>>> Publisher.objects.get(country="U.S.A.")
Traceback (most recent call last):
...
MultipleObjectsReturned: get() returned more than one Publisher --
it returned 2! Lookup parameters were {'country': 'U.S.A.'}
Запрос не возвращающий ни одного объекта тоже вызовет исключение: >>> Publisher.objects.get(name="Penguin")
Traceback (most recent call last):
...
DoesNotExist: Publisher matching query does not exist.
Исключение try:
p = Publisher.objects.get(name='Apress')
except Publisher.DoesNotExist:
print "Apress isn't in the database yet."
else:
print "Apress is in the database."
В процессе изучения предыдущих примеров вы могли заметить, что объекты возвращаются в случайном порядке. Раз мы не указали в каком порядке нам возвращать результат выборки, база данных отдаёт его в удобном для себя виде.
Очевидно, что для вашего приложения потребуется отсортировать
результат по какому-нибудь значению, скажем, по алфавиту. Для
этого использую метод >>> Publisher.objects.order_by("name")
[<Publisher: Apress>, <Publisher: O'Reilly>]
Это не сильно отличается от примера с методом
SELECT id, name, address, city, state_province, country, website FROM books_publisher ORDER BY name;
Мы можем производить сортировку по любому полю: >>> Publisher.objects.order_by("address")
[<Publisher: O'Reilly>, <Publisher: Apress>]
>>> Publisher.objects.order_by("state_province")
[<Publisher: Apress>, <Publisher: O'Reilly>]
Для выполнения сортировки по множеству полей (когда второе поле используется для сортировки элементов, у которых первое поле совпадает), используют множество аргументов: >>> Publisher.objects.order_by("state_province", "address")
[<Publisher: Apress>, <Publisher: O'Reilly>]
Также мы можем указать необходимость выполнять обратную сортировку с помощью префикса -(минус) для имени поля: >>> Publisher.objects.order_by("-name")
[<Publisher: O'Reilly>, <Publisher: Apress>]
Несмотря на все возможности, постоянное использование
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
def __unicode__(self):
return self.name
class Meta:
ordering = ["name"]
Здесь мы ввели новую концепцию: класс
Вы знаете как фильтровать данные и как их сортировать. Вы желаете узнать как это делать одновременно? Для этого следует «сцепить» операторы вместе: >>> Publisher.objects.filter(country="U.S.A.").order_by("-name")
[<Publisher: O'Reilly>, <Publisher: Apress>]
Как вы можете предполагать, в SQL представлении это будет выглядеть так: SELECT id, name, address, city, state_province, country, website FROM books_publisher WHERE country = 'U.S.A' ORDER BY name DESC;
Количество таких цепочек никак не ограничено[8]. Часто требуется получить только несколько строк результата выборки. Представьте, что в вашей базе находится несколько тысяч издателей, но вам надо отобразить только первого. Вы можете это осуществить с помощью возможностей стандартного списка Python: >>> Publisher.objects.order_by('name')[0]
<Publisher: Apress>
Это преобразуется в: SELECT id, name, address, city, state_province, country, website FROM books_publisher ORDER BY name LIMIT 1;
Аналогично, вы можете получать определённый набор данных с помощью стандартного синтаксиса языка Python для работы со списками: >>> Publisher.objects.order_by('name')[0:2]
Этот код вернёт два объекта и будет преобразован в: SELECT id, name, address, city, state_province, country, website FROM books_publisher ORDER BY name OFFSET 0 LIMIT 2;
Следует отметить, что отрицательные значения не поддерживаются: >>> Publisher.objects.order_by('name')[-1]
Traceback (most recent call last):
...
AssertionError: Negative indexing is not supported.
Но получить результат всё же возможно. Просто воспользуйтесь
методом >>> Publisher.objects.order_by('-name')[0]
Мы упоминали в разделе «Вставка и изменение данных» о том, что
метод
Например, нам требуется изменить в объекте
>>> p = Publisher.objects.get(name='Apress') >>> p.name = 'Apress Publishing' >>> p.save()
Это примерно преобразовывается в следующий SQL: SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE name = 'Apress';
UPDATE books_publisher SET
name = 'Apress Publishing',
address = '2855 Telegraph Ave.',
city = 'Berkeley',
state_province = 'CA',
country = 'U.S.A.',
website = 'http://www.apress.com'
WHERE id = 52;
(Следует отметить, что данный пример предполагает, что нужный нам объект имеет идентификатор 52.)
Вы можете видеть в данном примере, что метод
>>> Publisher.objects.filter(id=52).update(name='Apress Publishing')
SQL код будет более эффективным и не сможет вызвать «гонки»: UPDATE books_publisher SET name = 'Apress Publishing' WHERE id = 52;
Метод >>> Publisher.objects.all().filter(country='U.S.A.').update(country='USA') 2
Метод |
Found misprint?
Select it with the mouse and hit Enter
-
Processed:
33
1
199
25
The full repository of DjangoBook translation you can get on GitHub.
We appreciate your patches!
We are glad to hear your questions, comments or suggestions!
(Open in new tab)
Users number: 601
Русская группа
Ускорить процесс перевода!
ЯМ:41001223475816
|
| © 2008-2012 Ruslan Popov @ gmail.com | Powered by Django 1.2.5 |
>>> Publisher.objects.all()
[<Publisher: Apress>, <Publisher: O'Reilly>]
правильный вывод (согласно туториала):
[<Publisher: Addison-Wesley>, <Publisher: O'Reilly>, <Publisher: Apress Publishing>]