Question

I need to update an existing project to Django 1.5 to take advantage of its newly available custom user model. However, I'm having trouble migrating reusable apps that contain a model with a foreign key to a user. Currently, the foreign key points to auth.User but with a custom user model, it needs to point to myapp.CustomUser. Hence, some kind of migration is needed. I can't simply create a migration file for it because its a reusable app. It wouldn't be future proof because each time the app is updated, I would need to remember to create that migration again (there might even be migration conflicts) so it's not exactly a plausible solution.

Is there a solution to this problem other than to, maybe, fork each project, add a migration file, and then use that instead?

Some code:

models.py in reusable app

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 in my project

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

class CustomUser(AbstractUser):
    ...

settings.py in my project

AUTH_USER_MODEL = 'myapp.CustomUser'
Was it helpful?

Solution

So if the reusable app has a migration that creates a foreign key to a user, the following can be done to support Django 1.5's custom user model.

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)})
        }
    }

I'm not sure if this is the best solution but it's being used in apps such as django-reversion.

However, this solution still can pose a problem if you originally started with auth.User and then changed to myapp.customuser, simply because south is honors AUTH_USER_MODEL but the migration for the custom user model hasn't been created yet. This can occur during testing. Ticket #1179 of south addresses this issue (http://south.aeracode.org/ticket/1179).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top