December 23, 2023
Практические советы для начинающих django-разработчиков
Около месяца назад стартовали новый проект на Django и так вышло, что на нём работают Junior+ и Intern в паре. Причём, все последние проекты Junior+ разработчика были на FastAPI, из-за чего Django он подзабыл. По мере разработки я собирал в заметках все советы, которые давал разработчикам на проекте.
Для вашего удобства, я разбил советы по смысловым группам.
Общие советы
- старайтесь держать нейминг приложений согласованным, например, если вы назвали какое-то приложение в множественном числе, в то время, как все остальные названы в единственном числе, — это будет выглядеть неаккуратно;
- для чувствительных данных, вроде
SECRET_KEY
следует использовать переменные среды; - если вам необходимо быстро стартануть проект, вы можете использовать наш шаблон для django, всё настроено под работу через docker.
Разработка моделей
- когда вы делаете поле
ForeignKey
, не называйте егоmodel_name_id
, лучше простоmodel_name
, посколькуmodel_name_id
в случае FK резервируется ORM под возможность получать именно id, а не инстанс модели целиком, что позволяет избежать лишних запросов к БД; - если вы напишите человекочитаемый
verbose_name
у всех полей для каждой модели - это сильно облегчит пользование админкой Django; - если вы используете choices, вам следует завести их ключи свойствами класса модели, либо вынести их в отдельный класс, чтобы обращаться к константе, а не указывать конкретное значение, например:
# models.py from django.db import models class Student(models.Model): FRESHMAN = "FR" SOPHOMORE = "SO" JUNIOR = "JR" SENIOR = "SR" GRADUATE = "GR" YEAR_IN_SCHOOL_CHOICES = { FRESHMAN: "Freshman", SOPHOMORE: "Sophomore", JUNIOR: "Junior", SENIOR: "Senior", GRADUATE: "Graduate", } year_in_school = models.CharField( max_length=2, choices=YEAR_IN_SCHOOL_CHOICES, default=FRESHMAN, ) def is_upperclass(self): return self.year_in_school in {self.JUNIOR, self.SENIOR}
- зачастую вместо сигналов вам следует использовать хуки жизненного цикла (это стороннее решение), поскольку сигналы усложняют дебаг, особенно, когда их много, в то время как хуки жизненного цикла указываются в классе модели, что позволяет чётко понимать, на какое действие они ориентированы;
- в том же случае, если вы решили всё-таки использовать сигнал и он по какой-то причине не срабатывает, убедитесь, что вы его действительно подключили, мы обычно делаем это через функцию
ready
у класса конфигурации приложения, например:
# apps.py from django.apps import AppConfig class ExampleAppConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" name = "example_app" verbose_name = "Пример" def ready(self): # Implicitly connect signal handlers decorated with @receiver. from . import signals
Разработка API
- при написании представлений в Django старайтесь в названии представления отражать то, к чему оно действительно относится, также используйте нормальную форму, к примеру не
DetailedModelName
, аModelNameDetailView
; - при использовании DRF следует обратить внимание на такие библиотеки, как:
- drf-yasg — автодокументирование через swagger;
- djoser — библиотека, которая из коробки предоставляет вам готовое приложение для авторизации и регистрации различными способами;
- django-cors-headers — библиотека для настройки правил CORS внутри django-приложения;
- django-filter — удобная библиотека для написания фильтров.
Django settings
# Django-specific apps DJANGO_APPS = [ "jazzmin", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", ] # External apps THIRD_PARTY_APPS = [ "corsheaders", "rest_framework", "drf_spectacular", "djoser", "django_filters", "tinymce", "constance", ] # Internal apps INTERNAL_APPS = [ "users", ] INSTALLED_APPS = [*DJANGO_APPS, *THIRD_PARTY_APPS, *INTERNAL_APPS]
- не забудьте указать параметр
CSRF_TRUSTED_ORIGINS
(в противном случае, у вас может не работать админ-панель), референс.
Docker, docker-compose, gunicorn
- не забывайте про файл
.dockerignore
, это может значительно ускорить процесс сборки; - если при работе с
docker
вам не хватает hot reload (автоматическое применение изменений), вам необходимо сделать всего 2 вещи:
backend: image: template_django_core container_name: template_django_core build: ./django_core env_file: - ./django_core/.env command: gunicorn django_core.wsgi:application --bind 0.0.0.0:8000 --reload expose: - 8000 volumes: - ./django_core:/var/www/apps/django_core
- отличие директивы
expose
отports
заключается в том, что директиваports
экспортирует порт наружу из контейнера, аexpose
делает порт доступным внутри сети докера.
Админ-панель
- следует уделить отдельное внимание тому, как работает админ-панель и формы редактирования данных в ней, я писал об этом ранее, но приведу ссылку на stackoverflow;
- если вы хотите реализовать feature toggle, справочники или просто хранить любую редактируемую конфигурацию в админке, чтобы иметь возможность управлять ей без перезапуска приложения, вам стоит присмотреться к библиотеке django-constance;
- при настройке ModelAdmin, уделите отдельное внимание возможности fieldsets, поскольку так выводимая информация будет более структурированный.
Заключение
Надеюсь, собраннный материал оказался полезным для вас, если вам есть что добавить, поделитесь в комментариях, буду рад почитать.