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?
Ok, it turns out that South doesn’t freeze methods at all, so calling any model methods is of no use.
The way I solved this was by coping and modifying the code in contrib.auth that generates passwords.
Here’s how the final migration looks like: