# Советы по работе с ORM ## Создание моделей 1. Название модели пишется в единственном числе: `User`, `UserAnswer` 1. Название таблицы, если оно задается вручную, пишется во множественном числе в underscore: `users`, `user_answers`. 1. Поля модели и колонки в таблице пишутся в underscore: `login`, `first_name`. 1. Поля типа boolean начинаются с `is_`: `is_admin`, `is_hidden`. Есть некоторые исключения, в которых лучше написать грамотно. Например, `exists` вместо `is_exists`. Хоть последний вариант позволяет быстрее ориентироваться в типах полей, но он будет довольно сильно коробить других разработчиков. 1. Поля типов DATETIME заканчиваются на `_at`: `created_at`, `updated_at`. 1. Поля типов DATE заканчиваются на `_date`: `connect_date`, `end_date`. 1. Имя обратной связи для foreign key лучше по возможности не менять, если ORM задает его автоматически, т.к. иначе тем, кто читает код, будет не понятно, откуда вообще взялось это поле. Если всё-таки приходится задавать имя вручную для разрешения конфликтов (когда два поля ссылаются модели ссылаются на одну и ту же модель), лучше придерживаться того же стиля именования, что используется в ORM. Для Django это звучит как "имя связи заканчивается на `_set`". 1. Все связи должны задаваться именно как связи, а не просто поле типа `user_id`. Использование стандартного foreign key даст много преимуществ как на уровне БД, так и на уровне ORM. 1. Также важно сразу продумать и явно указать поведение модели при удалении связанных объектов. Например, нужно ли при удалении пользователя также удалять и его счета, или же просто установить связь в NULL. 1. Любое поле, которое не должно быть NULL, не должно быть NULL. То есть, для SQLAlchemy всегда пишите `nullable=False`, если не предполагается иное. Например, имя пользователя всегда `IS NOT NULL`, если только явно не предполагается наличие пользователей без имени. 1. Любое поле, хранящее уникальные значения, должно быть уникальным. Уникальность полей всегда должна проверяться на уровне БД. Всегда продумывайте, какие поля должны быть уникальными. Иногда это не одно поле, а их совокупность. 1. В качестве primary key в идеале должно выступать поле со следующими свойствами: целочисленный (для больших таблиц `BIGINT`, но иногда хватит даже `TINYINT`), `UNSIGNED`, `NOT NULL`, `AUTO_INCREMENT`. Не надо никаких UUID, если это реляционная БД. Это сэкономит объем, занимаемый каждой записью, и размер индекса, а также ускорит поиск и выборку данных. Одни плюсы. 1. По возможности всегда прописывайте для модели `__str__`, а также различные meta-параметры. Это пригодится при отображении объектов (в админке, формах, списках и т.д.) 1. Возможно, в какой-то момент вы захотите определенные объекты не удалять, а просто скрывать из интерфейса. Лучше учесть это заранее, т.к. в дальнейшем интеграция во все места в интерфесе будет долгой и с гораздо большими шансами где-то забыть это учесть. 1. Не используйте `default=[]` и `default={}` для `ArrayField` и `JSONField` — они шарятся между инстансами. Используйте `default=list` и `default=dict`. См. https://docs.djangoproject.com/en/1.11/ref/contrib/postgres/fields/#arrayfield [Виталий Котик](https://github.com/kotik) также советует побольше почитать про индексы: > Еще можно добавить про индексы, составные индексы, лидирующие колонки в составных индексах и что unique / unique_together работает как индекс. > Можно еще сказать что для сторок создается 2 типа индексов. И один из них очень пухлый на больших таблицах и его имеет смысл удалять вручную если не используется LIKE %pattern ## Работа с объектами 1. Не выбирайте из базы те колонки, которые не нужны. 1. Сразу выбирайте связанные модели, если будете использовать их в дальнейшем. 1. Не пишите просто `obj.save()`, если хотите просто обновить некоторые поля. Указывайте, что вы хотите сделать, и к каким это относится полям. Для Django это параметры `force_update` и `update_fields`. 1. Не выбирайте объекты, если их можно не выбирать. Постарайтесь, если это возможно, произвести все операции на уровне БД. Это не значит, что нужно строить крайне сложные запросы, но почти всегда это и не придётся делать. 1. Методы модели должны быть короткими и работать только с этой моделью и её связями. Любую существенную логику лучше вынести в отдельный controller. 1. Избегайте использования сигналов, т.к. это неявное поведение. При необходимости можно использовать [django-lifecycle](https://t.me/itgram_channel/134) или что-то похожее. К тому же в Django сигналы на `save` сработают только при вызове `obj.save()` и не будут срабатывать при вызове методов у `queryset`, таких как `update`, `delete`, `create`.