feat: Добавить систему мультитенантности с регистрацией магазинов
Реализована полноценная система мультитенантности на базе django-tenants. Каждый магазин получает изолированную схему БД и поддомен. Основные компоненты: Django-tenants интеграция: - Модели Client (тенант) и Domain в приложении tenants/ - Разделение на SHARED_APPS и TENANT_APPS - Public schema для общей админки - Tenant schemas для изолированных данных магазинов Система регистрации магазинов: - Публичная форма регистрации на /register/ - Модель TenantRegistration для заявок со статусами (pending/approved/rejected) - Валидация schema_name (латиница, 3-63 символа, уникальность) - Проверка на зарезервированные имена (admin, api, www и т.д.) - Админ-панель для модерации заявок с кнопками активации/отклонения Система подписок: - Модель Subscription с планами (триал 90 дней, месяц, квартал, год) - Автоматическое создание триальной подписки при активации - Методы is_expired() и days_left() для проверки статуса - Цветовая индикация в админке (зеленый/оранжевый/красный) Приложения: - tenants/ - управление тенантами, регистрация, подписки - shops/ - точки магазинов/самовывоза (tenant app) - Обновлены миграции для всех приложений Утилиты: - switch_to_tenant.py - переключение между схемами тенантов - Обновлены image_processor и image_service Конфигурация: - urls_public.py - роуты для public schema (админка + регистрация) - urls.py - роуты для tenant schemas (магазины) - requirements.txt - добавлены django-tenants, django-environ, phonenumber-field Документация: - DJANGO_TENANTS_SETUP.md - настройка мультитенантности - TENANT_REGISTRATION_GUIDE.md - руководство по регистрации - QUICK_START.md - быстрый старт - START_HERE.md - общая документация Использование: 1. Пользователь: http://localhost:8000/register/ → заполняет форму 2. Админ: http://localhost:8000/admin/ → активирует заявку 3. Результат: http://{schema_name}.localhost:8000/ - готовый магазин 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
297
myproject/START_HERE.md
Normal file
297
myproject/START_HERE.md
Normal file
@@ -0,0 +1,297 @@
|
||||
# 🚀 Чистый старт проекта с Django Tenants
|
||||
|
||||
Все миграции удалены. База данных пуста. Готов к чистому старту!
|
||||
|
||||
## ✅ Что уже сделано:
|
||||
|
||||
1. ✅ PostgreSQL установлен и запущен в Docker
|
||||
2. ✅ Все старые миграции удалены
|
||||
3. ✅ SQLite база удалена
|
||||
4. ✅ Проект настроен для django-tenants
|
||||
|
||||
---
|
||||
|
||||
## 📋 Пошаговая инструкция:
|
||||
|
||||
### Шаг 1: Установить зависимости
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Это установит:
|
||||
- django-tenants
|
||||
- psycopg2-binary
|
||||
- и все остальные зависимости
|
||||
|
||||
---
|
||||
|
||||
### Шаг 2: Создать миграции для всех приложений
|
||||
|
||||
```bash
|
||||
python manage.py makemigrations
|
||||
```
|
||||
|
||||
Django создаст миграции для:
|
||||
- **tenants** (public схема - Client и Domain)
|
||||
- **accounts, customers, shops, products, orders, inventory** (tenant схемы)
|
||||
|
||||
---
|
||||
|
||||
### Шаг 3: Применить миграции к public схеме
|
||||
|
||||
```bash
|
||||
python manage.py migrate_schemas --shared
|
||||
```
|
||||
|
||||
Это создаст:
|
||||
- Схему `public` в PostgreSQL
|
||||
- Таблицы для управления тенантами (Client, Domain)
|
||||
- Таблицы Django (auth, contenttypes, sessions, admin)
|
||||
|
||||
---
|
||||
|
||||
### Шаг 4: Создать public тенанта
|
||||
|
||||
Public тенант нужен для главного домена (localhost в разработке).
|
||||
|
||||
```bash
|
||||
python manage.py shell
|
||||
```
|
||||
|
||||
В shell выполните:
|
||||
|
||||
```python
|
||||
from tenants.models import Client, Domain
|
||||
|
||||
# Создать public тенанта
|
||||
public_tenant = Client.objects.create(
|
||||
schema_name='public',
|
||||
name='Главный домен',
|
||||
owner_email='admin@inventory.by',
|
||||
owner_name='Администратор'
|
||||
)
|
||||
|
||||
# Создать домен для public
|
||||
public_domain = Domain.objects.create(
|
||||
domain='localhost',
|
||||
tenant=public_tenant,
|
||||
is_primary=True
|
||||
)
|
||||
|
||||
print(f'✓ Public тенант создан: {public_tenant}')
|
||||
print(f'✓ Public домен создан: {public_domain}')
|
||||
exit()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Шаг 5: Создать суперпользователя (ваш аккаунт)
|
||||
|
||||
```bash
|
||||
python manage.py createsuperuser --schema=public
|
||||
```
|
||||
|
||||
Введите:
|
||||
- **Email**: ваш email
|
||||
- **Name**: ваше имя
|
||||
- **Password**: ваш пароль
|
||||
|
||||
Этот суперпользователь будет иметь доступ к админке на `localhost:8000/admin/` для управления тенантами.
|
||||
|
||||
---
|
||||
|
||||
### Шаг 6: Создать первый магазин (тенант)
|
||||
|
||||
```bash
|
||||
python manage.py create_tenant
|
||||
```
|
||||
|
||||
Пример данных:
|
||||
- **Название магазина**: Цветочный рай
|
||||
- **Схема БД**: shop1
|
||||
- **Домен**: shop1.localhost (или оставьте по умолчанию)
|
||||
- **Имя владельца**: Иван Иванов
|
||||
- **Email**: ivan@example.com
|
||||
- **Телефон**: (можете оставить пустым)
|
||||
|
||||
Команда автоматически:
|
||||
1. Создаст тенанта в таблице `Client`
|
||||
2. Создаст домен в таблице `Domain`
|
||||
3. Создаст схему `shop1` в PostgreSQL
|
||||
4. Применит все миграции к схеме `shop1`
|
||||
5. Создаст все таблицы (customers, orders, products, etc.) в схеме `shop1`
|
||||
|
||||
---
|
||||
|
||||
### Шаг 7: Настроить hosts файл
|
||||
|
||||
Откройте файл hosts с правами администратора:
|
||||
|
||||
**Windows**: `C:\Windows\System32\drivers\etc\hosts`
|
||||
|
||||
Добавьте строки:
|
||||
|
||||
```
|
||||
127.0.0.1 localhost
|
||||
127.0.0.1 shop1.localhost
|
||||
127.0.0.1 shop2.localhost
|
||||
```
|
||||
|
||||
Сохраните файл.
|
||||
|
||||
---
|
||||
|
||||
### Шаг 8: Запустить сервер
|
||||
|
||||
```bash
|
||||
python manage.py runserver 0.0.0.0:8000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Шаг 9: Проверить работу
|
||||
|
||||
#### 1. Админка супер-администратора (Public схема):
|
||||
|
||||
URL: **http://localhost:8000/admin/**
|
||||
|
||||
Логин: email и пароль суперпользователя (из Шага 5)
|
||||
|
||||
Здесь вы увидите:
|
||||
- Управление тенантами (магазинами)
|
||||
- Управление доменами
|
||||
- Стандартные разделы Django
|
||||
|
||||
#### 2. Админка магазина (Tenant схема):
|
||||
|
||||
URL: **http://shop1.localhost:8000/admin/**
|
||||
|
||||
Сначала нужно создать пользователя для магазина:
|
||||
|
||||
```bash
|
||||
python manage.py tenant_command createsuperuser --schema=shop1
|
||||
```
|
||||
|
||||
Затем зайдите в админку магазина и увидите:
|
||||
- Клиенты (Customers)
|
||||
- Адреса (Addresses)
|
||||
- Магазины/точки (Shops)
|
||||
- Товары (Products, Categories, Kits)
|
||||
- Заказы (Orders, OrderItems)
|
||||
- Складской учет (Inventory)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Проверка изоляции данных
|
||||
|
||||
Создайте второй магазин:
|
||||
|
||||
```bash
|
||||
python manage.py create_tenant
|
||||
```
|
||||
|
||||
Данные (название: "Второй магазин", схема: "shop2", домен: "shop2.localhost")
|
||||
|
||||
Затем:
|
||||
1. Добавьте товары в shop1
|
||||
2. Добавьте товары в shop2
|
||||
3. Убедитесь, что товары из shop1 НЕ видны в shop2 и наоборот
|
||||
|
||||
**Это и есть полная изоляация данных!** ✅
|
||||
|
||||
---
|
||||
|
||||
## 🛠 Полезные команды
|
||||
|
||||
### Посмотреть список всех тенантов:
|
||||
|
||||
```bash
|
||||
python manage.py shell
|
||||
```
|
||||
|
||||
```python
|
||||
from tenants.models import Client
|
||||
for tenant in Client.objects.all():
|
||||
print(f'{tenant.name}: {tenant.schema_name} - {tenant.get_primary_domain()}')
|
||||
```
|
||||
|
||||
### Применить миграции ко всем тенантам:
|
||||
|
||||
```bash
|
||||
python manage.py migrate_schemas
|
||||
```
|
||||
|
||||
### Применить миграции к конкретному тенанту:
|
||||
|
||||
```bash
|
||||
python manage.py migrate_schemas --schema=shop1
|
||||
```
|
||||
|
||||
### Выполнить команду для тенанта:
|
||||
|
||||
```bash
|
||||
python manage.py tenant_command <command> --schema=shop1
|
||||
```
|
||||
|
||||
Примеры:
|
||||
```bash
|
||||
python manage.py tenant_command createsuperuser --schema=shop1
|
||||
python manage.py tenant_command shell --schema=shop1
|
||||
python manage.py tenant_command dumpdata --schema=shop1 > shop1_data.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Структура базы данных
|
||||
|
||||
После выполнения всех шагов в PostgreSQL будет:
|
||||
|
||||
### Схема `public`:
|
||||
- Таблицы тенантов: `tenants_client`, `tenants_domain`
|
||||
- Таблицы Django: `auth_user`, `auth_group`, `django_session`, etc.
|
||||
|
||||
### Схема `shop1`:
|
||||
- `customers_customer`, `customers_address`
|
||||
- `shops_shop`
|
||||
- `products_product`, `products_category`, `products_productkit`
|
||||
- `orders_order`, `orders_orderitem`
|
||||
- `inventory_*`
|
||||
- И все остальные таблицы приложений
|
||||
|
||||
### Схема `shop2`:
|
||||
- Те же таблицы что и в `shop1`, но с ДРУГИМИ данными!
|
||||
|
||||
---
|
||||
|
||||
## ❗ Возможные проблемы
|
||||
|
||||
### Ошибка: "connection to server at localhost (127.0.0.1), port 5432 failed"
|
||||
PostgreSQL не запущен. Запустите:
|
||||
```bash
|
||||
docker start inventory-postgres
|
||||
```
|
||||
|
||||
### Ошибка: "database 'inventory_db' does not exist"
|
||||
Создайте базу:
|
||||
```bash
|
||||
docker exec -it inventory-postgres psql -U postgres -c "CREATE DATABASE inventory_db;"
|
||||
```
|
||||
|
||||
### Ошибка: "No tenant found for hostname 'shop1.localhost'"
|
||||
- Проверьте hosts файл
|
||||
- Проверьте, что домен создан: `Domain.objects.filter(domain='shop1.localhost').exists()`
|
||||
|
||||
### Ошибка: "relation does not exist"
|
||||
Миграции не применены. Запустите:
|
||||
```bash
|
||||
python manage.py migrate_schemas
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Готово!
|
||||
|
||||
После выполнения всех шагов у вас будет работающая SaaS-платформа с полной изоляцией данных между магазинами!
|
||||
|
||||
**Подробная документация**: [DJANGO_TENANTS_SETUP.md](DJANGO_TENANTS_SETUP.md)
|
||||
Reference in New Issue
Block a user