Files
octopus/myproject/tenants/admin_mixins.py
Andrey Smakotin eb6a3c1874 Исправлена ошибка public admin для мультитенантной архитектуры
Проблема: при входе в localhost/admin/ (public схема) возникала ошибка
"relation user_roles_userrole does not exist", так как tenant-only
таблицы не существуют в public схеме.

Решение:
- Создан TenantAdminOnlyMixin для скрытия tenant-only моделей от public admin
- Применён миксин ко всем ModelAdmin классам в tenant-only приложениях:
  user_roles, customers, orders, inventory, products
- Добавлена проверка _is_public_schema() в RoleBasedPermissionBackend
  для предотвращения запросов к tenant-only таблицам в public схеме

Теперь:
- localhost/admin/ показывает только public модели (Client, Domain, User)
- shop.localhost/admin/ показывает все модели магазина

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 01:05:47 +03:00

92 lines
3.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- 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