Перейти к содержанию

Первая модель

Пройдём весь путь от начала до конца: опишем модель, создадим её таблицу и выполним простые запросы.

1. Описываем модель

# library/models.py
from hare import fields
from hare.models import Model


class Author(Model):
    id = fields.UUIDField(primary_key=True)
    name = fields.CharField(max_length=120)
    email = fields.CharField(max_length=254, unique=True, null=True)
    created_at = fields.DatetimeField(auto_now_add=True)

    class Meta:
        table_description = "Book authors"
        ordering = ("-created_at",)


class Book(Model):
    id = fields.UUIDField(primary_key=True)
    author = fields.ForeignKeyField("models.Author", related_name="books", on_delete=fields.CASCADE)
    title = fields.CharField(max_length=300)
    published_at = fields.DateField(null=True)

Модель — обычный класс, унаследованный от hare.models.Model. Поля — это атрибуты класса, а всё, что относится к таблице целиком, — её имя, порядок строк, ограничения — задаётся во вложенном классе Meta. Полное описание — в разделах Типы полей и Опции Meta.

2. Подключаем hare

# library/db.py
from hare import Hare, HareConfig

async def init_db() -> None:
    await Hare.init(HareConfig.from_db_url("sqlite+aiosqlite://db.sqlite3", {"models": ["library.models"]}))
    await Hare.generate_schemas()

generate_schemas() создаёт таблицы прямо по описаниям моделей — этого достаточно, чтобы быстро начать или прогнать тесты. Для базы, которая будет работать на сервере, используйте миграции — см. Создание и применение миграций.

3. Создаём строки и читаем их

from library.models import Author, Book

async def run() -> None:
    author = await Author.objects.create(name="Ursula K. Le Guin", email="ukl@example.com")
    await Book.objects.create(author=author, title="The Left Hand of Darkness")
    await Book.objects.create(author=author, title="The Dispossessed")

    # все книги авторов, в имени которых есть «le guin», вместе с автором в том же запросе
    async for book in Book.objects.filter(author__name__icontains="le guin").select_related("author"):
        print(book.title, "—", book.author.name)

    # одна строка или None
    maybe = await Author.objects.get(email="ukl@example.com", does_not_exist_exception=None)

    # подсчёт, изменение, удаление — обычные возможности QuerySet
    total = await Book.objects.filter(author=author).count()
    await Book.objects.filter(title__istartswith="the").update(published_at=None)
    await author.delete()  # вместе с автором удалятся его книги: on_delete=CASCADE

Все методы QuerySet — filter, annotate, values, bulk_create, prefetch_related и остальные — описаны в разделе Методы QuerySet.

Дальше в документации такие операторы показаны без окружающего async def: каждый фрагмент выполняется внутри async-кода с hare, инициализированным как на шаге 2, а модели импортируют from hare import fields и from hare.models import Model.

Что дальше