В этом уроке мы научимся:
- сортировать данные в Django ORM;
- изменять записи в базе;
- выполнять массовые обновления;
- удалять записи с помощью ORM-запросов;
На предыдущем уроке мы научились выбирать данные из базы и фильтровать их по нужным условиям.
Теперь мы сделаем следующий шаг — научимся управлять этими данными: изменять, сортировать и удалять.
Для примеров будем использовать модель Movie из проекта CinemaHub:
class Movie(models.Model):
title = models.CharField(max_length=100)
year = models.PositiveIntegerField()
rating = models.FloatField(default=0)
is_published = models.BooleanField(default=True)
time_create = models.DateTimeField(auto_now_add=True)
time_update = models.DateTimeField(auto_now=True)
def __str__(self):
return self.titleИногда нам нужно не просто вывести все фильмы, а сделать это в определённом порядке: по алфавиту, по рейтингу, по дате выхода и т.д.
Для этого в Django ORM используется метод order_by().
Movie.objects.order_by('title')Такой запрос отсортирует все фильмы в алфавитном порядке (по возрастанию, ASC).
SQL-запрос при этом будет выглядеть так:
SELECT * FROM movies_movie ORDER BY title ASC;Чтобы отсортировать записи в обратном порядке, добавляем знак - перед именем поля:
Movie.objects.order_by('-rating')Теперь фильмы будут выведены от самого высокого рейтинга к низкому.
SQL:
SELECT * FROM movies_movie ORDER BY rating DESC;Часто сортировка используется вместе с фильтрацией:
Movie.objects.filter(is_published=True).order_by('-year')Такой запрос сначала отберёт опубликованные фильмы, а затем отсортирует их по году — от новых к старым.
Если вы хотите, чтобы данные всегда возвращались в определённом порядке, можно задать сортировку прямо в модели:
class Movie(models.Model):
...
class Meta:
ordering = ['-time_create']Теперь даже простой запрос:
Movie.objects.all()будет автоматически отсортирован по дате создания (от новых к старым).
-
Запустите Django shell:
python manage.py shell_plus --print-sql
-
Проверьте сортировку фильмов:
Movie.objects.order_by('title') Movie.objects.order_by('-year')
-
Затем откройте в браузере ваш список фильмов — убедитесь, что порядок отображения изменился.
Иногда нужно обновить данные — например, изменить название фильма или исправить ошибку в годе выпуска.
Получаем объект, изменяем поля, сохраняем изменения:
movie = Movie.objects.get(pk=2)
movie.title = 'Interstellar (2014)'
movie.rating = 9.0
movie.save()SQL-запрос, который сгенерирует Django:
UPDATE movies_movie SET title = 'Interstellar (2014)', rating = 9.0 WHERE id = 2;После этого обновите страницу в браузере — изменения должны отобразиться.
Когда нужно обновить сразу несколько записей — используем update().
Например, сделаем все фильмы неопубликованными:
Movie.objects.update(is_published=False)Или изменим статус только у фильмов до 2010 года:
Movie.objects.filter(year__lt=2010).update(is_published=True)SQL-запрос:
UPDATE movies_movie SET is_published = 1 WHERE year < 2010;-
update()нельзя применять к отдельным объектам:Movie.objects.get(pk=1).update(is_published=False) # Ошибка!
-
update()нельзя использовать со срезами:Movie.objects.all()[:3].update(is_published=True) # Ошибка!
Метод работает только с QuerySet, то есть с выборкой, а не с отдельной записью.
Теперь давайте научимся удалять данные.
Movie.objects.filter(year__lt=2000).delete()SQL-запрос:
DELETE FROM movies_movie WHERE year < 2000;Movie.objects.all().delete()Но использовать это стоит очень осторожно — команда удалит абсолютно все фильмы из таблицы.
Если нужно удалить один конкретный фильм:
movie = Movie.objects.get(pk=5)
movie.delete()После удаления можно проверить, что запись исчезла:
Movie.objects.filter(pk=5)
# <QuerySet []>После любого изменения — обновления или удаления — всегда полезно проверить данные визуально.
Например, если у вас есть представление:
def movies_list(request):
movies = Movie.objects.filter(is_published=True).order_by('-year')
return render(request, 'movies/movies_list.html', {'movies': movies})После обновлений или удалений просто обновите страницу — и вы сразу увидите изменения, сделанные через ORM.
Выведите список всех фильмов, отсортированных по году выпуска по возрастанию.
Выведите только опубликованные фильмы (is_published=True), отсортировав их по названию.
Найдите фильм с pk=3 и измените его рейтинг на 8.7.
Обновите флаг is_published на True для всех фильмов, выпущенных после 2015 года.
Удалите все фильмы, у которых рейтинг меньше 5.
После каждого шага откройте страницу со списком фильмов и убедитесь, что изменения действительно применились.
- Какой метод используется для сортировки записей в Django ORM?
- Как отсортировать записи по убыванию рейтинга?
- Что делает параметр
orderingвнутри классаMeta? - Чем отличаются методы
save()иupdate()? - Почему
update()нельзя использовать на одной записи? - Как удалить все фильмы, год которых меньше 2010?
- Как проверить, что запись успешно удалена?
- Как можно задать сортировку “по умолчанию” для модели?
- Как обновить несколько записей одним запросом?
- Почему важно проверять изменения через браузер после выполнения ORM-запросов?