Проблема: при входе в 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>
92 lines
3.9 KiB
Python
92 lines
3.9 KiB
Python
# -*- 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
|