МОДЕЛИ DJANGO И ORM

ПРИМЕРЫ ЗАПРОСОВ И МИГРАЦИЙ

Модели Django и ORM

Модели Django и ORM

Модели, миграции, QuerySet

Модель — это таблица, описанная классом

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

class Post(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    body = models.TextField()
    is_published = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

Метод __str__ не обязателен, но без него в админке вместо названий будет «Post object (1)».

Основные типы полей

  • CharField — строка фиксированной длины, обязателен max_length.
  • TextField — длинный текст без ограничения.
  • BooleanField — да или нет, удобно для публикации.
  • DateTimeField — дата и время; auto_now_add ставит дату при создании.
  • ForeignKey — связь «много к одному»: у статьи один автор.
  • DecimalField — деньги; для цен забудьте про Float, он теряет копейки.

Миграции

Любое изменение моделей фиксируется миграцией — это версионирование схемы базы. Две команды, которые нужны каждый раз: makemigrations создаёт файл с изменениями, migrate применяет его к базе. Файлы миграций хранятся в репозитории: по ним другой разработчик или сервер соберёт такую же схему.

Запросы через ORM

ORM заменяет SQL конструкциями Python. Базовые операции:

Post.objects.create(title="Первый пост", slug="first", body="Текст")
Post.objects.filter(is_published=True).order_by("-created_at")
Post.objects.get(slug="first")
Post.objects.exclude(title__icontains="тест")
Post.objects.filter(is_published=True).count()

Двойное подчёркивание отделяет поле от операции: title__icontains, views__gte, status__in, deleted_at__isnull.

F и Q. Для сравнения полей между собой и для сложных условий:

from django.db.models import F, Q
Post.objects.filter(views__gt=F("likes"))
Post.objects.filter(Q(is_published=True) | Q(is_featured=True))

select_related. Если выводите 20 статей и у каждой обращаетесь к автору, Django сделает 21 запрос к базе. Это проблема N+1, и решается она так: Post.objects.select_related("author") — один запрос вместо двадцати одного. Для связей «многие ко многим» есть prefetch_related.

Частые ошибки

  • Править схему вручную. Изменение таблицы в обход миграций приводит к тому, что миграции перестают видеть расхождения.
  • Использовать get для поиска в списке. Он падает с ошибкой, если записей ноль или больше одной. Для списков — filter.
  • Забыть про индексы. Поле, по которому часто ищут, должно иметь db_index=True.
  • Тянуть всё в память. Выборка на 100 000 записей съест гигабайт. Для перебора — iterator(), для списков — пагинация.

Нужен сайт на Django, а не статья?

Сделаю проект под ключ: модели данных, админка, интеграции с 1С и оплатой, REST API, деплой на ваш сервер с HTTPS и резервными копиями. С 2009 года, по договору, с поддержкой после запуска.

ОБСУДИТЬ ПРОЕКТ

Полезно по теме: установка Django, views и URL, деплой на VPS, обзор Django.