Найти в Дзене
AERONYTE

Установка PostgreSQL 16 для Django 5 с поддержкой русской локали, .env, полнотекстового поиска, pg_trgm и GIN-индексов

Оглавление

Хотите подключить Django 5 к PostgreSQL 16 на macOS с полной поддержкой русского языка, полнотекстового поиска, часового пояса МСК и безопасным хранением секретов в .env?

В этой инструкции вы узнаете:

  • Как удалить старые версии PostgreSQL и корректно установить PostgreSQL 16 с ru_RU.UTF-8;
  • Как инициализировать кластер с русским полнотекстовым поиском;
  • Как создать отдельного пользователя и базу для Django;
  • Как настроить подключение в settings.py и загрузку переменных из .env;
  • Какие пакеты нужно установить, чтобы всё сразу заработало;
  • Какие вопросы по этой теме часто задают на собеседованиях junior–middle–senior уровней.

📌 Всё изложено на уровне senior с пояснениями, комментариями и примерами. В конце статьи вас ждут вопросы, которые задают на собеседовании по этой теме.

1.1. Удаление старых версий PostgreSQL (если были)

brew services list

Результат:

-2

PostgreSQL 16 уже установлен. Давайте я его удалю и покажу процесс удаления и установки.

Если есть другие версии PostgreSQL выполните команды:

brew services stop postgresql@16
brew uninstall postgresql@16
rm -rf /opt/homebrew/var/postgresql@16*
rm -rf ~/Library/LaunchAgents/homebrew.mxcl.postgresql@16.plist

Проверьте, нет ли работающих процессов:

ps aux | grep postgres

Если процессы postgres остались — убейте их вручную:

killall postgres

1.2. Установка PostgreSQL 16

brew install postgresql@16

Добавим в PATH:

echo 'export PATH="/opt/homebrew/opt/postgresql@16/bin:$PATH"' >> ~/.zprofile
source ~/.zprofile

1.3. Инициализация кластера с русской локалью и текстовым поиском

initdb --locale=ru_RU.UTF-8 --encoding=UTF-8 --text-search-config=russian /opt/homebrew/var/postgresql@16

Если видишь initdb: предупреждение: включение trust — это ок для разработки.

1.4. Запуск PostgreSQL

pg_ctl -D /opt/homebrew/var/postgresql@16 -l ~/pg16.log start

Или как сервис:

brew services start postgresql@16

1.5. Проверка

psql -U alex -d postgres

1.6 Создаём пользователя и базу данных в PostgreSQL 16 для работы с Django 5

Запускаем psql:

psql -U alex -d postgres

Внутри psql выполняем:

-3
-- 1. Создать пользователя для Django
CREATE USER django_user WITH PASSWORD 'пароль';
-- 2. Создать базу данных с русской локалью и нужным владельцем
CREATE DATABASE django_db
WITH OWNER = django_user
ENCODING = 'UTF8'
LC_COLLATE = 'ru_RU.UTF-8'
LC_CTYPE = 'ru_RU.UTF-8'
TEMPLATE = template0;
-- 3. Подключиться к созданной базе данных
\c django_db
-- 4. Установить необходимые расширения (внутри django_db)
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS unaccent;
-- 5. Убедиться, что у пользователя есть все права на базу
GRANT ALL PRIVILEGES ON DATABASE django_db TO django_user;

1.7 Настройка файла для хранения секретов .env

Создайте файл .env в корне проекта:

SECRET_KEY=your-very-secret-django-key
DEBUG=True
DB_NAME=django_db
DB_USER=django_user
DB_PASSWORD=пароль
DB_HOST=localhost
DB_PORT=5432

1.8. Настройка settings.py Django 5

Добавьте в начало файла импорты:

import os
from dotenv import load_dotenv
from pathlib import Path
load_dotenv()

Секретный ключ:

SECRET_KEY = os.getenv("SECRET_KEY")

Отладка и разрешённые хосты:

DEBUG = os.getenv("DEBUG", "False") == "True"
ALLOWED_HOSTS = ["127.0.0.1", "localhost"]

Подключение к PostgreSQL 16:

DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.getenv("DB_NAME"),
"USER": os.getenv("DB_USER"),
"PASSWORD": os.getenv("DB_PASSWORD"),
"HOST": os.getenv("DB_HOST", "localhost"),
"PORT": os.getenv("DB_PORT", "5432"),
}
}

Должно быть так в файле settings.py:

-4

Настройки языка и часового пояса

LANGUAGE_CODE = "ru"
TIME_ZONE = "Europe/Moscow"
USE_I18N = True
USE_L10N = True
USE_TZ = True

1.9 Установка необходимых зависимостей Django 5 для работы с PostgreSQL 16 и .env

В виртуальной среде (my_env) вашего проекта Django 5 выполните:

pip install "psycopg[binary]" python-dotenv

Результат:

-5

Объяснение:

  • psycopg — это новый psycopg3 (в отличие от psycopg2), и он использует extras-style установку: psycopg[binary], psycopg[c], и т.п.
  • binary означает установку сборки с нативным C-бинарем, не требующей компиляции.
  • Он полностью совместим с Django 4.2 и 5.0+.

Итог:

Вы установили:

  • psycopg[binary] — официальную библиотеку для подключения Django 5 к PostgreSQL 16 (совместима с Django 5).
  • python-dotenv — для загрузки переменных из .env.

1.10 Проверка соединения и миграция

Создайте миграции:

python manage.py makemigrations

Результат:

-6

Выполните миграцию:

python manage.py migrate

Результат:

-7

Если соединение прошло успешно — будет создана структура базы.

Создание GIN-индекса с pg_trgm через Django-механизм миграций

Чтобы ускорить поиск с опечатками, по подстроке (icontains, ilike, search) — достаточно один раз создать GIN-индекс с pg_trgm для нужного текстового поля.

Django позволяет сделать это через кастомную миграцию:

На скриншоте представлен список миграций и код для новой миграции для создания GIN-индекс с pg_trgm.
На скриншоте представлен список миграций и код для новой миграции для создания GIN-индекс с pg_trgm.

from django.contrib.postgres.indexes import GinIndex
from django.db import migrations
dep_02 = (
'0002_alter_post_options_alter_post_author_alter_post_body_and_more'
)
class Migration(migrations.Migration):
dependencies = [
('blog', dep_02),
]
operations = [
migrations.AddIndex(
model_name='post',
index=GinIndex(
name='idx_post_title_trgm',
fields=['title'],
opclasses=['gin_trgm_ops'],
),
),
]

Примечание:

  • gin_trgm_ops — операторный класс для pg_trgm, ускоряющий LIKE, ILIKE, icontains, trigram_similar.
  • GinIndex — нативный способ Django выразить индекс USING gin(...).

В модели Posts приложения необходимо добавить индексы:

-9
-10

from django.contrib.postgres.indexes import GinIndex
indexes = [
models.Index(fields=["-publish"]),
GinIndex(
name="idx_post_title_trgm",
fields=["title"],
opclasses=["gin_trgm_ops"],
),
GinIndex(
name="idx_post_body_trgm",
fields=["body"],
opclasses=["gin_trgm_ops"],
),
]

Теперь создайте миграцию:

python manage.py makemigrations

Примените миграцию:

python manage.py migrate

Результат:

Миграция для создания GIN-индекс с pg_trgm успешно создана через команду python manage.py migrate.
Миграция для создания GIN-индекс с pg_trgm успешно создана через команду python manage.py migrate.

Что это даёт?

Post.objects.filter(title__icontains="пушкн")

Без индекса: будет Seq Scan — PostgreSQL прочитает все строки таблицы.

С индексом: используется Index Scan по GIN-индексу — быстро и эффективно, даже при большом объёме данных.

Это особенно полезно при реализации:

  • полнотекстового поиска с опечатками;
  • автодополнения;
  • похожих названий;
  • «живого поиска» по заголовкам, авторам, категориям и т.д.

Производительность на больших таблицах увеличивается в десятки раз.

Итог: создавая GIN-индексы через миграции, вы не только ускоряете поиск, но и делаете проект устойчивым к развертыванию на разных машинах — от локалки до Docker и продакшена.

Конечная цель достигнута

Теперь у вас полностью готова среда для профессиональной разработки на Django 5+ с PostgreSQL 16:

  • Django 5 подключен к PostgreSQL 16 — через современный драйвер psycopg[binary];
  • Используется .env — для безопасного хранения ключей и конфигурации;
  • Локаль базы данных — ru_RU.UTF-8 — корректно работает кириллица, сортировка и сравнение строк на русском языке;
  • Часовой пояс — Europe/Moscow — всё отображается в нужной временной зоне;
  • Подключены расширения pg_trgm и unaccent — PostgreSQL умеет искать слова с опечатками и без учёта регистра или акцентов;
  • Создан GIN-индекс с gin_trgm_ops через миграцию Django — поиск по подстроке (icontains, LIKE, ILIKE) теперь быстрый даже при больших объёмах данных;
  • Полноценно работает полнотекстовый поиск с морфологией (pg_catalog.russian) — вы можете реализовать поисковик уровня «Яндекса на своём сайте».

🛠 Это фундамент для:

  • современных блогов, маркетплейсов, агрегаторов;
  • быстрых REST/GraphQL API;
  • сервисов со сложными поисковыми запросами.

📦 Такой стек — must-have для любого backend‑разработчика, который готов работать с продакшеном, CI/CD и нагрузкой.

Вопросы на собеседовании: Django + PostgreSQL 16 + .env + локализация + полнотекстовый поиск

🟢 Junior-уровень

  • Какой движок базы данных используется по умолчанию в Django и почему?
  • Как сменить SQLite на PostgreSQL в Django-проекте?
  • Что такое файл .env и зачем его использовать?
  • Как передаются переменные окружения из .env в settings.py?
  • Как задать русский язык (ru) и часовой пояс (Europe/Moscow) в settings.py?
  • Что делает DEBUG=True и почему это опасно на продакшене?
  • Как проверить, что соединение с PostgreSQL установлено?
  • Что делает команда python manage.py migrate?
  • Что такое миграции и в каком порядке они выполняются?
  • Чем отличается makemigrations от migrate?

🟡 Middle-уровень

  • Чем отличается load_dotenv() от прямого использования os.environ.get()?
  • Какие переменные для подключения к PostgreSQL ты указываешь в .env?
  • Как создать нового пользователя и базу данных в PostgreSQL с нужной локалью?
  • Что такое USE_TZ = True и как Django работает с временными зонами?
  • Как инициализировать кластер PostgreSQL с русской локалью? Что делает initdb?
  • Что такое pg_trgm и зачем нужно расширение unaccent?
  • Как работает SearchVector, SearchQuery, SearchRank в Django?
  • Что такое TSVECTOR и как он используется в полнотекстовом поиске?
  • Чем отличаются индексы GIN и GiST? Где их уместно применять?
  • Как протестировать подключение к БД и запуск запросов вне Django (psql, SQLAlchemy и т.п.)?
  • Как написать кастомную миграцию Django для создания GIN-индекса?

🔴 Senior-уровень

  • Как защитить .env в CI/CD пайплайне? Где он должен храниться в продакшене?
  • Как ты конфигурируешь PostgreSQL (например: shared_buffers, work_mem, effective_cache_size) под высокую нагрузку?
  • Как реализовать полнотекстовый поиск на русском языке с учётом морфологии?
  • Что делает gin_trgm_ops, и как его использовать через Django-механизм миграций?
  • Как устроен SearchVectorField? В каких случаях его стоит использовать?
  • Какие best practices по загрузке переменных окружения в Docker/Heroku/Cloud.ru?
  • Как организовать централизованную миграцию и управление индексами в команде?
  • Как проводить аудит безопасности settings.py перед публикацией на прод?
  • Как реализовать горизонтальное масштабирование Django + PostgreSQL?
  • Как настроить репликацию и failover для PostgreSQL на продакшене?
  • Что такое seq scan vs index scan? Как понять, какой тип используется?
  • Как с помощью EXPLAIN ANALYZE понять, работает ли индекс pg_trgm?

🎓 Заключение

Теперь у вас полностью настроен Django 5+ проект, подключённый к PostgreSQL 16 с:

  • русской локалью и часовым поясом Москва — для корректной сортировки и работы с датами;
  • поддержкой полнотекстового поиска на русском языке с морфологией (pg_catalog.russian);
  • установленными расширениями pg_trgm и unaccent — для поиска с опечатками и без учёта регистра;
  • GIN‑индексами, созданными через миграции Django — для быстрых icontains и LIKE‑запросов;
  • надёжным хранением переменных в .env и безопасной интеграцией в settings.py.

Это — фундамент для серьёзных продакшен‑проектов, ориентированных на русскоязычных пользователей, с высокими требованиями к:

  • скорости поиска,
  • локализации,
  • масштабируемости,
  • и чистоте кода.

Такой стек — обязательный минимум для backend‑разработчика уровня middle+, который хочет уверенно работать с:

  • CI/CD,
  • DevOps‑процессами,
  • настройкой индексов и миграций,
  • безопасной работой с данными.

Если материал оказался полезен — сохрани в закладки, поделись с командой, или сделай себе шпаргалку на основе этого гайда.