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:
70
myproject/switch_to_tenant.py
Normal file
70
myproject/switch_to_tenant.py
Normal file
@@ -0,0 +1,70 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Скрипт для переключения в пространство конкретного тенанта.
|
||||
|
||||
Использование:
|
||||
python switch_to_tenant.py grach
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import django
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
|
||||
django.setup()
|
||||
|
||||
from django.db import connection
|
||||
from tenants.models import Client
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Использование: python switch_to_tenant.py <schema_name>")
|
||||
print("\nДоступные тенанты:")
|
||||
for client in Client.objects.all():
|
||||
print(f" - {client.schema_name}: {client.name}")
|
||||
sys.exit(1)
|
||||
|
||||
schema_name = sys.argv[1]
|
||||
|
||||
try:
|
||||
# Находим тенанта
|
||||
client = Client.objects.get(schema_name=schema_name)
|
||||
print(f"Найден тенант: {client.name} ({client.schema_name})")
|
||||
|
||||
# Переключаемся на схему тенанта
|
||||
connection.set_tenant(client)
|
||||
print(f"Переключено на схему: {connection.tenant.schema_name}")
|
||||
print("")
|
||||
|
||||
# Теперь можем работать с данными тенанта
|
||||
print("=" * 60)
|
||||
print("Теперь вы работаете в контексте тенанта!")
|
||||
print("=" * 60)
|
||||
print("")
|
||||
|
||||
# Примеры работы с данными тенанта
|
||||
from products.models import Product
|
||||
from customers.models import Customer
|
||||
from orders.models import Order
|
||||
|
||||
products_count = Product.objects.count()
|
||||
customers_count = Customer.objects.count()
|
||||
orders_count = Order.objects.count()
|
||||
|
||||
print(f"Товары: {products_count}")
|
||||
print(f"Клиенты: {customers_count}")
|
||||
print(f"Заказы: {orders_count}")
|
||||
print("")
|
||||
|
||||
# Интерактивный режим
|
||||
print("Запуск интерактивной оболочки...")
|
||||
print("Вы можете использовать: Product, Customer, Order и другие модели")
|
||||
print("")
|
||||
|
||||
import code
|
||||
code.interact(local=locals())
|
||||
|
||||
except Client.DoesNotExist:
|
||||
print(f"Ошибка: Тенант с schema_name '{schema_name}' не найден")
|
||||
print("\nДоступные тенанты:")
|
||||
for client in Client.objects.all():
|
||||
print(f" - {client.schema_name}: {client.name}")
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user