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

Мне нужно обновить существующий проект до Django 1.5, чтобы воспользоваться новой доступной настраиваемой пользовательской моделью. Однако у меня возникают проблемы с переносом повторно используемых приложений, содержащих модель с внешним ключом, на пользователя. В настоящее время внешний ключ указывает на auth.User, но с пользовательской моделью пользователя он должен указывать на myapp.CustomUser. Следовательно, необходима какая-то миграция. Я не могу просто создать для него файл миграции, потому что это многоразовое приложение. Это не было бы доказательством будущего, потому что каждый раз, когда приложение обновляется, мне нужно будет не забыть создать эту миграцию снова (могут даже возникнуть конфликты миграции), так что это не совсем правдоподобное решение.

Есть ли решение этой проблемы, кроме, возможно, разветвления каждого проекта, добавления файла миграции, а затем использования его вместо этого?

Некоторый код:

models.py в многоразовом приложении

from django.conf import settings
from django.db import models

UserModel = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')

class ModelA(models.Model):
    user = models.ForeignKey(UserModel)

models.py в моем проекте

from django.conf import settings
from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    ...

settings.py в моем проекте

AUTH_USER_MODEL = 'myapp.CustomUser'

person SunnySydeUp    schedule 18.03.2013    source источник


Ответы (1)


Таким образом, если повторно используемое приложение имеет миграцию, которая создает внешний ключ для пользователя, для поддержки пользовательской модели пользователя Django 1.5 можно сделать следующее.

try:
    from django.contrib.auth import get_user_model
except ImportError: # django < 1.5
    from django.contrib.auth.models import User
else:
    User = get_user_model()

class Migration(SchemaMigration):

    def forwards(self, orm):
        db.create_table('reusableapp.modela', (
            ('user', self.gf('django...ForeignKey')(to=orm["%s.%s" % (User._meta.app_label, User._meta.object_name)])

    models = {
        ...
        # this should replace "auth.user"
        "%s.%s" % (User._meta.app_label, User._meta.module_name): {
        'Meta': {'object_name': User.__name__},
        }
        "reusableapp.modela": {
             'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s.%s']"% (User._meta.app_label, User._meta.object_name)})
        }
    }

Я не уверен, что это лучшее решение, но оно используется в таких приложениях, как django-reversion.

Однако это решение по-прежнему может создавать проблемы, если вы изначально начали с auth.User, а затем изменили на myapp.customuser просто потому, что юг учитывает AUTH_USER_MODEL, но миграция для пользовательской модели пользователя еще не создана. Это может произойти во время тестирования. Эта проблема решается в билете № 1179 на юг (http://south.aeracode.org/ticket/1179).

person SunnySydeUp    schedule 20.03.2013
comment
Вместо этого нельзя было бы сделать что-то вроде User = getattr(settings, 'AUTH_USER_MODEL', 'auth.User') ... to=orm[User] ... 'to':orm['%s'] % Пользователь ? - person askvictor; 19.07.2013
comment
Это решение действительно страдает от оценки времени выполнения и разрешения пользователя. Таким образом, если вы использовали auth.User на своем сайте в версии X, а в версии Y измените его на пользовательскую модель, некоторые или все ваши сценарии миграции мгновенно станут неработоспособными. - person mbargiel; 04.09.2013
comment
Я предполагаю, что решение состоит в том, чтобы это было принято во внимание в South, чтобы соответствующая информация о замороженной модели пользователя добавлялась к информации о миграции, а не полагалась на интеллектуальный импорт на основе текущих настроек. Тем временем это будет работать для любого сайта, которому не нужно переходить с auth.User на настраиваемого пользователя (или с настраиваемого пользователя на другого настраиваемого пользователя, или даже обратно на auth.User). - person mbargiel; 04.09.2013