# -*- coding: utf-8 -*- """ Миксины для Django Admin в мультитенантной архитектуре. ЗАЧЕМ ЭТО НУЖНО: ================ В django-tenants есть две схемы БД: - public: общая схема (тенанты, домены, пользователи) - tenant: отдельная схема для каждого магазина (товары, заказы, клиенты) Проблема: Django Admin регистрирует ВСЕ модели глобально. Когда суперадмин заходит на localhost/admin/ (public схема), Django пытается показать sidebar со ВСЕМИ моделями, включая tenant-only модели (Order, Product, UserRole). Но таблицы этих моделей существуют только в схемах тенантов! В public схеме их нет -> ошибка "relation does not exist". РЕШЕНИЕ: ======== Миксин TenantAdminOnlyMixin скрывает модель от админки, если мы находимся в public схеме. Модель просто не показывается в sidebar и недоступна по URL. ИСПОЛЬЗОВАНИЕ: ============== from tenants.admin_mixins import TenantAdminOnlyMixin @admin.register(Order) class OrderAdmin(TenantAdminOnlyMixin, admin.ModelAdmin): ... Теперь Order будет виден только в админке тенанта (shop.localhost/admin/), но не в public админке (localhost/admin/). """ from django_tenants.utils import get_public_schema_name class TenantAdminOnlyMixin: """ Миксин для скрытия tenant-only моделей от public admin. Как работает: - has_module_permission() вызывается Django для проверки, показывать ли модель в sidebar админки - Мы проверяем текущую схему БД - Если это public схема -> возвращаем False (скрыть) - Если это схема тенанта -> возвращаем True (показать) """ def has_module_permission(self, request): """ Скрыть модуль (группу моделей) от public schema админки. Вызывается при отрисовке sidebar и при доступе к URL модели. """ from django.db import connection # Получаем имя public схемы (обычно 'public') public_schema = get_public_schema_name() # Если мы в public схеме - скрываем модель if connection.schema_name == public_schema: return False # В схеме тенанта - показываем (используем стандартную проверку) return super().has_module_permission(request) class PublicAdminOnlyMixin: """ Обратный миксин - показывать модель ТОЛЬКО в public admin. Полезно для моделей типа Client, Domain, TenantRegistration, которые должны быть доступны только суперадмину на главном домене. Примечание: обычно не нужен, так как эти модели и так существуют только в public схеме. """ def has_module_permission(self, request): """Показать модуль только в public schema админке.""" from django.db import connection public_schema = get_public_schema_name() # Показываем только в public схеме if connection.schema_name == public_schema: return super().has_module_permission(request) return False