Если вы пришли с Django¶
Модели, запросы и миграции hare устроены так же, как в Django, поэтому почти всё, что знает разработчик на Django, остаётся в силе. На этой странице — что называется иначе, что работает так же и где hare даёт другой результат. Остальная документация описывает hare саму по себе.
Что называется иначе¶
| Django | hare |
|---|---|
from django.db import models, models.Model |
from hare import fields, from hare.models import Model |
models.ForeignKey, models.OneToOneField, models.ManyToManyField |
fields.ForeignKeyField, fields.OneToOneField, fields.ManyToManyField — см. Связи |
GenericForeignKey из contenttypes |
fields.GenericForeignKeyField |
Meta.db_table, Meta.app_label, Meta.db_table_comment |
Meta.table, Meta.app, Meta.table_description — см. Опции Meta |
Meta.unique_together |
UniqueConstraint(fields=(...)) в Meta.constraints |
settings.DATABASES, DATABASE_ROUTERS |
connections и routers в Hare.init() |
transaction.atomic(), transaction.on_commit() |
Transactions.atomic(), Transactions.on_commit() — см. Транзакции |
ATOMIC_REQUESTS |
atomic_requests интеграции с веб-фреймворком — см. Веб-фреймворки |
manage.py makemigrations, migrate, sqlmigrate, squashmigrations, inspectdb |
hare makemigrations, hare migrate, hare sqlmigrate, hare squashmigrations, hare inspectdb — см. Команда hare |
django.utils.timezone.override() |
Timezone.override() (from hare.time import Timezone) |
Каждый запрос и каждая запись — корутина: await Book.objects.filter(...), async for book in ...,
await book.save(). on_delete по умолчанию — CASCADE.
Что работает так же¶
- Цепочка маршрутизаторов: побеждает первый, вернувший псевдоним, а чтение, от которого зависит запись
(
get_or_create(),update_or_create(),select_for_update()), идёт через подключение для записи. on_commit(), вызванный после окончания транзакции, выполняет колбэк сразу.- Путь к полю может заканчиваться связью или
pk;relation=Noneу связи «ко многим» — этоrelation__isnull=True; оператор по имени самой связи сравнивает её ключ. - Неявный
GROUP BYуvalues().annotate(), и агрегат, добавленный доvalues(), считается для каждой строки модели. update_fields=["author"]записываетauthor_id;ForeignKeyFieldсоздаёт индекс по колонке ключа;add(),remove()иset()связи «многие-ко-многим» принимают объекты или значения ключа.Index(fields=("-created_at",))— ключ по убыванию; условие ограничения — этоQ.- Запрос со срезом нельзя фильтровать, пересортировать или сделать
distinct(); агрегировать можно. distinct()с сортировкой по невыбранной колонке выбирает и её, поэтому выбранное значение может прийти несколько раз — см.values()иvalues_list().
Где hare даёт другой результат¶
exclude()через связь «ко многим». Условия одного вызоваexclude()относятся к одной и той же связанной строке, как вfilter():exclude(books__name="a", books__rating=5)оставляет автора, у которого одна книга называется «a», а другая имеет оценку 5. Django отбрасывает и его; в hare для этого нужны два вызова —.exclude(books__name="a").exclude(books__rating=5). См.exclude().filter()иannotate()в любом порядке.annotate(n=Count("books")).filter(books__price__gt=6)используетJOINагрегата и считает только подходящие книги — так же, какfilter(...).annotate(...). В Django от порядка число меняется. См. Агрегаты и фильтры по связям «ко многим».- Агрегаты по двум связям «ко многим». Сумма или число, которые второй
JOIN«ко многим» завысил бы, даютQueryError, а не завышенное значение, которое возвращает Django. get()уunion(). Принимает условия и применяет их к каждой ветке; Django их не принимает.