НейроАгент

Исправление ошибки миграции в Django Multi-Tenant: relation does not exist

Полное руководство по исправлению ошибки 'relation does not exist' при выполнении migrate_schemas --shared в Django multi-tenant приложениях. Узнайте о правильной настройке приложений, порядке миграции и решениях для управления схемами.

Как исправить ошибку “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:
python
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 определена следующим образом:

python
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 должна понимать, какие таблицы принадлежат какой схеме и в каком порядке они должны создаваться.


Основные причины ошибки

На основе исследований, несколько факторов могут способствовать возникновению этой ошибки:

  1. Неправильная конфигурация приложений: Приложение с пользовательской моделью пользователя может быть неправильно включено в правильный список приложений (SHARED_APPS против TENANT_APPS)

  2. Проблемы с порядком миграции: Миграции применяются в порядке, который ссылается на таблицы, которые еще не существуют

  3. Проблемы состояния схемы: Существующее состояние схемы может быть несогласованным с текущим состоянием миграции

  4. Отсутствующие зависимости: Необходимые компоненты аутентификации Django могут быть неправильно настроены для работы с multi-tenant


Пошаговые решения

Решение 1: Правильная конфигурация приложений

Наиболее распространенным исправлением является обеспечение правильной конфигурации приложений с включением необходимых компонентов в правильных местах. На основе результатов исследований:

  1. Добавьте django.contrib.auth в SHARED_APPS:
python
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
]
  1. Проверьте конфигурацию TENANT_APPS:
python
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: Правильный порядок миграции

Следуйте этой конкретной последовательности, чтобы убедиться, что миграции применяются в правильном порядке:

  1. Сначала сгенерируйте миграции для всех приложений:
bash
python manage.py makemigrations
python manage.py makemigrations users
python manage.py makemigrations tenants
python manage.py makemigrations core
  1. Сначала мигрируйте общую схему:
bash
python manage.py migrate_schemas --shared
  1. Затем мигрируйте отдельные схемы:
bash
python manage.py migrate_schemas

Как сообщил один пользователь: “Однако мне пришлось запустить makemigrations для приложений users и tenants (где у меня есть мои модели django_tenant), и после этого миграция прошла идеально.”

Решение 3: Пересоздание схемы

Если приведенные выше решения не работают, вам может потребоваться пересоздать схемы:

  1. Удалите существующие схемы (сначала создайте резервную копию данных!):
bash
python manage.py flush_schemas
  1. Сбросьте миграции (опционально, но иногда необходимо):
bash
python manage.py migrate users zero
python manage.py migrate tenants zero
  1. Снова следуйте правильной последовательности миграции:
bash
python manage.py makemigrations
python manage.py migrate_schemas --shared
python manage.py migrate_schemas

Решение 4: Ручной подход к миграции

Для более сложных сценариев вам может потребоваться вручную контролировать процесс миграции:

  1. Создайте пользовательскую команду миграции:
python
# в 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)
  1. Запустите пользовательскую команду миграции:
bash
python manage.py migrate_schemas_safe

Стратегии предотвращения

Чтобы избежать этой ошибки в будущем:

  1. Всегда включайте django.contrib.auth в SHARED_APPS при использовании пользовательских моделей пользователей

  2. Запускайте makemigrations перед migrate в средах разработки

  3. Тестируйте последовательности миграций в среде разработки перед применением в продакшене

  4. Используйте систему контроля версий для отслеживания файлов миграций и обеспечения согласованности между средами

  5. Регулярно создавайте резервные копии базы данных перед выполнением операций миграции


Альтернативные подходы

Если вы продолжаете сталкиваться с проблемами, рассмотрите эти альтернативные подходы:

  1. Используйте другой подход к модели пользователя:

    • Рассмотрите возможность сделать вашу модель пользователя действительно специфичной для арендатора
    • Или используйте совершенно отдельную систему аутентификации для общей схемы
  2. Решения на уровне базы данных:

    • Вручную создайте необходимые таблицы перед запуском миграций
    • Используйте представления базы данных для абстрагирования различий схем
  3. Рассмотрите альтернативные multi-tenant решения:

    • Оцените, подходит ли django-tenants для вашего случая использования
    • Изучите другие multi-tenant пакеты, которые могут лучше обрабатывать пользовательские модели

Заключение

Ошибка “relation does not exist” при запуске migrate_schemas --shared с пользовательскими моделями в django-tenants является распространенной, но решаемой проблемой. Ключевые решения включают:

  1. Правильную настройку SHARED_APPS и TENANT_APPS для включения всех необходимых компонентов
  2. Следование правильной последовательности миграции с правильными шагами makemigrations
  3. Возможное пересоздание схем после изменений конфигурации
  4. Использование ручных подходов к миграции для сложных сценариев

Помните, что после внесения изменений в конфигурацию вам, вероятно, потребуется удалить существующие схемы и мигрировать их заново, как указано в результатах исследований. Всегда создавайте резервную копию базы данных перед выполнением операций миграции и тщательно тестируйте в среде разработки в первую очередь.

Источники

  1. r/django на Reddit: Django_tenants + custom user model migration errors
  2. r/django на Reddit: Has anyone used django-tenant-schemas that can answer this question about users?
  3. Stack Overflow: Deploying a multi tenant application (django-tenant) - Error to run ./manage migrate_schemas
  4. Stack Overflow: multi tenant - django.db.utils.ProgrammingError: relation “users_user” does not exist
  5. GitHub Issue: Using django-tenant-schemas doesn’t apply my AUTH_USER_MODEL when running migrate_schema
  6. GitHub Issue: “tenants_client” does not exist when I run migrate schemas in django 3