views:

57

answers:

1

Instead of using django's auth module I've used my own and already regret it a lot.

In an effort to rectify the situation, I'm trying to migrate the data from my User model to django.auth.models.User.

I've created a data migration as follows:

def forwards(self, orm):
    """Migrate user information from mooi User model to auth User model."""

    OldUser = orm['mooi.User']
    User = orm['auth.User']
    Profile = orm['mooi.Profile']

    oldUsers = OldUser.objects.all()
    for oldUser in oldUsers:
        newUser = User.objects.create_user(username=oldUser.id, email=oldUser.email, password=oldUser.password)
        # ...more irrelevant code follows...

When I run the migration, I get this error (traceback):

#...irrelevant traceback precedes...
File "[projdir]/mooi/migrations/0005_from_mooi_users_create_auth_users_with_profiles.py", line 18, in forwards
    newUser = User.objects.create_user(username=oldUser.id, email=oldUser.email, password=oldUser.password)
  File "[virtual_env_dir]lib/python2.6/site-packages/south/orm.py", line 397, in __getattr__
    return getattr(self.real, name)
AttributeError: 'Manager' object has no attribute 'create_user'

Upon further investigation, I discovered that the Manager that was being referred to was of time south.orm.NoDryRunManager which explains the error.

Now, the reason I even need create_user is to create a password hash that django.contrib.auth will understand.

Having said all that, how do I go about doing this? What's the most elegant solution given the hole I'm in?!

Thanks in advance.

Update 1

As suggested by stevejalim, I tried to use User's set_password(...) as follows:

newUser.set_password(raw_password=oldUser.password)
newUser.save()

However that failed with this error:

File "[projdir]/mooi/migrations/0005_from_mooi_users_create_auth_users_with_profiles.py", line 21, in forwards
    newUser.set_password(raw_password=oldUser.password)
AttributeError: 'User' object has no attribute 'set_password'

I did find a hint in the south documentation which states that:

South doesn’t freeze every aspect of a model; for example, it doesn’t preserve new managers, or custom model methods, as these would require serialising the python code that runs those method (and the code that depends on, and so forth).

If you want custom methods in your migration, you’ll have to copy the code in, including any imports it relies on to work. Remember, however, for every import that you add, you’re promising to keep that import valid for the life for the migration.

I guess the question remains, what's the best/safest way of doing this? Copy the set_password(...) method over? Create a function that hashes the password for me? Any other ideas?

A: 

Why not make the User manually, then set the password after it has been save()d with newUser.set_password()? Yes, you'll need to hit the DB twice, but that's no great shakes.

stevejalim
Not a bad idea, except, I still get an error: AttributeError: 'User' object has no attribute 'set_password'.
Pilgrim
In that case, lift the code from django.contrib.auth.models.User for set_password() [and get_hexdigest()] - it's about 30 lines all-in
stevejalim