Пошаговая инструкция по установке библиотеки, настройке settings.py и созданию публичного и tenant-приложений.
Пошаговая инструкция по интеграции django-tenants в ваш Django-проект.
Перед началом убедитесь, что у вас есть:
Установите django-tenants через pip:
pip install django-tenantsИли через Poetry:
poetry add django-tenantsСоздайте новое приложение для моделей тенанта. Обычно его называют customers или tenants:
python manage.py startapp customersВ файле customers/models.py определите модели Client и Domain:
from django.db import models
from django_tenants.models import TenantMixin, DomainMixin
class Client(TenantMixin):
"""
Модель клиента (тенанта).
Каждый экземпляр представляет одного клиента с собственной схемой.
"""
name = models.CharField(max_length=100, help_text="Название компании")
description = models.TextField(blank=True)
created_on = models.DateField(auto_now_add=True)
active = models.BooleanField(default=True)
# Обязательно для TenantMixin
auto_create_schema = True # Автоматически создавать схему при создании тенанта
class Domain(DomainMixin):
"""
Модель домена.
Связывает доменные имена с тенантами.
"""
# DomainMixin уже содержит поля domain и tenant
# Можно добавить дополнительные поля при необходимости
passВажно:
TenantMixin добавляет необходимые поля и методы для работы со схемамиauto_create_schema = True автоматически создаёт схему при сохранении тенантаDomainMixin содержит поля domain (доменное имя) и tenant (связь с Client)Откройте settings.py и внесите следующие изменения:
INSTALLED_APPS = [
# Приложения django-tenants (обязательно в начале!)
'django_tenants',
'customers', # Ваше приложение с моделями Client и Domain
# Django apps
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Ваши shared apps (если есть)
# Ваши tenant apps (будут созданы позже)
]DATABASES = {
'default': {
'ENGINE': 'django_tenants.postgresql_backend',
'NAME': 'saas_db',
'USER': 'postgres',
'PASSWORD': 'your_password',
'HOST': 'localhost',
'PORT': '5432',
}
}Важно: Обратите внимание на ENGINE — используется специальный бэкенд django_tenants.postgresql_backend.
DATABASE_ROUTERS = (
'django_tenants.routers.TenantSyncRouter',
)Роутер автоматически направляет запросы в правильную схему.
TENANT_MODEL = "customers.Client"
TENANT_DOMAIN_MODEL = "customers.Domain"Укажите пути к вашим моделям в формате app_label.ModelName.
Это ключевая настройка, определяющая, какие приложения создаются в схемах тенантов, а какие — только в public:
SHARED_APPS = (
# Django apps (обязательно)
'django_tenants',
'customers',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Ваши shared apps
# Например, приложение с тарифами, общими настройками
)
TENANT_APPS = (
# Ваши tenant apps
# Приложения, данные которых принадлежат конкретному тенанту
'django.contrib.contenttypes', # Обязательно для tenant apps
'django.contrib.auth', # Если нужна аутентификация в tenant
'projects', # Ваше приложение с проектами
'tasks', # Ваше приложение с задачами
)Разница:
public schema. Данные общие для всех.Альтернативный способ — использовать списки:
SHARED_APPS = [
'django_tenants',
'customers',
# ...
]
TENANT_APPS = [
'django.contrib.contenttypes',
# ...
]
# Обязательно установите эти переменные
INSTALLED_APPS = SHARED_APPS + TENANT_APPS# Показывать схемы в админке
SHOW_PUBLIC_IF_NO_TENANT_FOUND = True
# Кастомизация URL для tenant admin
TENANT_ADMIN_URL = 'admin/'Создайте приложения, которые будут работать в схемах тенантов:
python manage.py startapp projects
python manage.py startapp tasksВ projects/models.py:
from django.db import models
from django_tenants.models import TenantModel
class Project(TenantModel):
"""
Проект принадлежит конкретному тенанту.
Наследуется от TenantModel, а не от models.Model.
"""
name = models.CharField(max_length=200)
description = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
# Важно для tenant models
app_label = 'projects'В tasks/models.py:
from django.db import models
from django_tenants.models import TenantModel
class Task(TenantModel):
"""
Задача принадлежит проекту и, следовательно, тенанту.
"""
project = models.ForeignKey('projects.Project', on_delete=models.CASCADE)
title = models.CharField(max_length=200)
completed = models.BooleanField(default=False)
class Meta:
app_label = 'tasks'Если у вас есть приложения с общими данными, создайте их:
python manage.py startapp billingВ billing/models.py:
from django.db import models
from django_tenants.models import SharedModel
class Plan(SharedModel):
"""
Тарифный план — общий для всех тенантов.
Наследуется от SharedModel.
"""
name = models.CharField(max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2)
max_projects = models.IntegerField(default=10)
class Meta:
app_label = 'billing'python manage.py makemigrationsСначала примените миграции для shared apps:
python manage.py migrate_schemas --sharedЭта команда создаст таблицы в схеме public.
python manage.py migrate_schemas --tenantЭта команда создаст таблицы tenant apps в public schema (шаблон для будущих тенантов).
Важно: При создании нового тенанта django-tenants автоматически применит миграции tenant apps к его схеме.
Суперпользователь создаётся в public schema:
python manage.py createsuperuserЗапустите Django shell:
python manage.py shellСоздайте тенанта:
from customers.models import Client, Domain
# Создайте клиента
client = Client.objects.create(
name='Acme Inc',
description='Первый клиент',
active=True
)
# Создайте домен для клиента
domain = Domain.objects.create(
domain='acme.localhost:8000', # Для локальной разработки
tenant=client,
is_primary=True
)
print(f"Тенант создан: {client.name}, схема: {client.schema_name}")По умолчанию schema_name генерируется автоматически (например, acme_inc).
Зайдите в админку (/admin/) и создайте Client и Domain через интерфейс.
python manage.py runserverПерейдите на http://localhost:8000/admin/ — вы увидите админку с общими данными.
Для доступа к данным тенанта используйте домен:
http://acme.localhost:8000/admin/
Важно: Для локальной разработки добавьте в /etc/hosts:
127.0.0.1 acme.localhost
Или используйте middleware для переключения тенантов в разработке.
django-tenants автоматически добавляет необходимый middleware. Убедитесь, что в MIDDLEWARE есть:
MIDDLEWARE = [
'django_tenants.middleware.TenantMiddleware',
# Остальные middleware...
]TenantMiddleware определяет тенанта по домену и переключает схему.
# Неправильно
'ENGINE': 'django.db.backends.postgresql'
# Правильно
'ENGINE': 'django_tenants.postgresql_backend'# Неправильно
INSTALLED_APPS = [
'django.contrib.admin',
'django_tenants', # Должно быть первым!
]
# Правильно
INSTALLED_APPS = [
'django_tenants',
'customers',
'django.contrib.admin',
]# Неправильно
class Project(models.Model): # Не будет работать в tenant schema
# Правильно
class Project(TenantModel): # Будет создано в схеме тенанта# Неправильно
python manage.py migrate # Не создаст таблицы для tenant apps
# Правильно
python manage.py migrate_schemas --shared
python manage.py migrate_schemas --tenantТеперь у вас есть работающая настройка django-tenants. В следующей теме вы узнаете больше о моделях и миграциях в мультитенантной среде.
Переходите к следующей теме → Модели и миграции
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.