Как исправить ошибку “django.db.utils.ProgrammingError: relation ‘users_user’ does not exist” при выполнении команды python manage.py migrate_schemas --shared в мультиарендном приложении Django?
Я столкнулся со следующей ошибкой при попытке запустить миграции для общей схемы в моем мультиарендном приложении Django:
django.db.utils.ProgrammingError: relation "users_user" does not exist
Ошибка возникает при выполнении:
python manage.py migrate_schemas --shared
Структура моего проекта включает:
- Пользовательскую модель User в приложении
users - Мультиарендную настройку с использованием django-tenants
- Следующую конфигурацию в файле settings.py:
AUTH_USER_MODEL = 'users.User'
SHARED_APPS = [
'django_tenants',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crispy_forms',
'crispy_bootstrap5',
'django_htmx',
'django_celery_beat',
'core',
'tenants',
]
TENANT_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users',
'accreditation',
'documents',
'checklists',
'notifications',
'reports',
'audit',
]
Моя модель User определена следующим образом:
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
ROLE_CHOICES = [
('super_admin', 'Super Admin'),
('org_admin', 'Organization Admin'),
('dept_user', 'Department User'),
('auditor', 'Auditor'),
]
role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='dept_user')
tenant = models.ForeignKey('tenants.Tenant', on_delete=models.CASCADE, null=True, blank=True)
phone = models.CharField(max_length=15, blank=True)
department = models.CharField(max_length=100, blank=True)
class Meta:
db_table = 'users_user'
Полный стек ошибки показывает, что проблема возникает в процессе миграции, конкретно при попытке применить миграцию admin.0001_initial. Как можно решить эту ошибку миграции и убедиться, что таблица users_user корректно создается в общей схеме?
Ошибка “django.db.utils.ProgrammingError: relation ‘users_user’ does not exist”
Ошибка “django.db.utils.ProgrammingError: relation ‘users_user’ does not exist” обычно возникает, когда Django-tenants не могут найти таблицу пользовательской модели пользователя во время миграции общей схемы. Это происходит потому, что процесс миграции пытается сослаться на таблицы, которые еще не созданы из-за неправильной конфигурации приложений или порядка миграции.
Содержание
- Понимание проблемы
- Основные причины ошибки
- Пошаговые решения
- Стратегии предотвращения
- Альтернативные подходы
- Заключение
Понимание проблемы
Ошибка ProgrammingError: relation "users_user" does not exist возникает конкретно при выполнении python manage.py migrate_schemas --shared в настройке Django multi-tenant. Эта ошибка указывает на то, что процесс миграции пытается получить доступ к таблице users_user до того, как она будет создана в общей схеме.
Как объясняет один пользователь Reddit, это распространенная проблема при использовании пользовательских моделей с django-tenants: “Чтобы исправить это, добавьте django.contrib.auth в SHARED_APPS или TENANT_APPS, где его нет. А ТЕПЕРЬ ВАЖНАЯ ЧАСТЬ. Я почти уверен, что после этого вам придется удалить схему и мигрировать ее заново”.
Проблема возникает из-за сложных отношений между общими и специфичными для арендатора схемами, где система миграции Django должна понимать, какие таблицы принадлежат какой схеме и в каком порядке они должны создаваться.
Основные причины ошибки
На основе исследований, несколько факторов могут способствовать возникновению этой ошибки:
-
Неправильная конфигурация приложений: Приложение с пользовательской моделью пользователя может быть неправильно включено в правильный список приложений (SHARED_APPS против TENANT_APPS)
-
Проблемы с порядком миграции: Миграции применяются в порядке, который ссылается на таблицы, которые еще не существуют
-
Проблемы состояния схемы: Существующее состояние схемы может быть несогласованным с текущим состоянием миграции
-
Отсутствующие зависимости: Необходимые компоненты аутентификации Django могут быть неправильно настроены для работы с multi-tenant
Пошаговые решения
Решение 1: Правильная конфигурация приложений
Наиболее распространенным исправлением является обеспечение правильной конфигурации приложений с включением необходимых компонентов в правильных местах. На основе результатов исследований:
- Добавьте django.contrib.auth в SHARED_APPS:
SHARED_APPS = [
'django_tenants',
'django.contrib.admin',
'django.contrib.auth', # Убедитесь, что это включено
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crispy_forms',
'crispy_bootstrap5',
'django_htmx',
'django_celery_beat',
'core',
'tenants',
'users', # Добавьте ваше приложение users в SHARED_APPS
]
- Проверьте конфигурацию TENANT_APPS:
TENANT_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users', # Оставьте users в обоих, если необходимо
'accreditation',
'documents',
'checklists',
'notifications',
'reports',
'audit',
]
Важно: Согласно исследованиям, после внесения этих изменений “вам придется удалить схему и мигрировать ее заново”, чтобы получить правильное состояние.
Решение 2: Правильный порядок миграции
Следуйте этой конкретной последовательности, чтобы убедиться, что миграции применяются в правильном порядке:
- Сначала сгенерируйте миграции для всех приложений:
python manage.py makemigrations
python manage.py makemigrations users
python manage.py makemigrations tenants
python manage.py makemigrations core
- Сначала мигрируйте общую схему:
python manage.py migrate_schemas --shared
- Затем мигрируйте отдельные схемы:
python manage.py migrate_schemas
Как сообщил один пользователь: “Однако мне пришлось запустить makemigrations для приложений users и tenants (где у меня есть мои модели django_tenant), и после этого миграция прошла идеально.”
Решение 3: Пересоздание схемы
Если приведенные выше решения не работают, вам может потребоваться пересоздать схемы:
- Удалите существующие схемы (сначала создайте резервную копию данных!):
python manage.py flush_schemas
- Сбросьте миграции (опционально, но иногда необходимо):
python manage.py migrate users zero
python manage.py migrate tenants zero
- Снова следуйте правильной последовательности миграции:
python manage.py makemigrations python manage.py migrate_schemas --shared python manage.py migrate_schemas
Решение 4: Ручной подход к миграции
Для более сложных сценариев вам может потребоваться вручную контролировать процесс миграции:
- Создайте пользовательскую команду миграции:
# в management/commands/migrate_schemas_safe.py
from django.core.management import call_command
from django_tenants.utils import tenant_context
class Command(BaseCommand):
def handle(self, *args, **options):
# Сначала мигрируем общую схему
call_command('migrate_schemas', '--shared', interactive=False)
# Затем мигрируем отдельные схемы
call_command('migrate_schemas', interactive=False)
- Запустите пользовательскую команду миграции:
python manage.py migrate_schemas_safe
Стратегии предотвращения
Чтобы избежать этой ошибки в будущем:
-
Всегда включайте django.contrib.auth в SHARED_APPS при использовании пользовательских моделей пользователей
-
Запускайте
makemigrationsпередmigrateв средах разработки -
Тестируйте последовательности миграций в среде разработки перед применением в продакшене
-
Используйте систему контроля версий для отслеживания файлов миграций и обеспечения согласованности между средами
-
Регулярно создавайте резервные копии базы данных перед выполнением операций миграции
Альтернативные подходы
Если вы продолжаете сталкиваться с проблемами, рассмотрите эти альтернативные подходы:
-
Используйте другой подход к модели пользователя:
- Рассмотрите возможность сделать вашу модель пользователя действительно специфичной для арендатора
- Или используйте совершенно отдельную систему аутентификации для общей схемы
-
Решения на уровне базы данных:
- Вручную создайте необходимые таблицы перед запуском миграций
- Используйте представления базы данных для абстрагирования различий схем
-
Рассмотрите альтернативные multi-tenant решения:
- Оцените, подходит ли django-tenants для вашего случая использования
- Изучите другие multi-tenant пакеты, которые могут лучше обрабатывать пользовательские модели
Заключение
Ошибка “relation does not exist” при запуске migrate_schemas --shared с пользовательскими моделями в django-tenants является распространенной, но решаемой проблемой. Ключевые решения включают:
- Правильную настройку SHARED_APPS и TENANT_APPS для включения всех необходимых компонентов
- Следование правильной последовательности миграции с правильными шагами
makemigrations - Возможное пересоздание схем после изменений конфигурации
- Использование ручных подходов к миграции для сложных сценариев
Помните, что после внесения изменений в конфигурацию вам, вероятно, потребуется удалить существующие схемы и мигрировать их заново, как указано в результатах исследований. Всегда создавайте резервную копию базы данных перед выполнением операций миграции и тщательно тестируйте в среде разработки в первую очередь.
Источники
- r/django на Reddit: Django_tenants + custom user model migration errors
- r/django на Reddit: Has anyone used django-tenant-schemas that can answer this question about users?
- Stack Overflow: Deploying a multi tenant application (django-tenant) - Error to run ./manage migrate_schemas
- Stack Overflow: multi tenant - django.db.utils.ProgrammingError: relation “users_user” does not exist
- GitHub Issue: Using django-tenant-schemas doesn’t apply my AUTH_USER_MODEL when running migrate_schema
- GitHub Issue: “tenants_client” does not exist when I run migrate schemas in django 3