Django, BigIntegerField, and django.contrib.auth.user.id
Django now provides a BigIntegerField for use in django models (available in svn trunk and also 1.2 alpha-1 release).
I need my django.co开发者_如何学运维ntrib.auth.user model to have a BigIntegerField as its auto-incrementing primary key, whereas it currently uses an auto-incrementing IntegerField as its primary key. Also, wherever contrib.auth.user is used as a ForeginKey, it would need to be BigIntegerField as well.
What is the best and safest way to go about achieving this?
While I'm not sure why you need a BigIntegerField on User (you must have a whole lotta users) its pretty easy to implement. First you'll need to get a database migration system like South. We'll use this to do a handful of migrations of your current data. If you don't have anything in your database then just ignore this part and skip to the end.
I would start by making a custom user class which inherits from the contrib.auth version like so:
from django.contrib.auth.models import User, UserManager
from django.db import models
class BigUser(User):
id = models.BigIntegerField(pk = True)
objects = UserManager()
#this lets you transperantly use any
#query methods that you could on User
Then use South's data-migration capability to make a copy of all of you User.objects.all()
into your new BigUser
model.
Then go through and ADD a foriegnkey in each model where its needed. DO NOT delete the original FK yet, otherwise you're links will be lost. After adding the new keys do another schema migration.
Then make another data migration which copies the FK's from the old User model to the new BigUser model. Migrate that data.
Then its safe to delete the old FK to the User model.
If you want to avoid changing the rest of your code to use the new field-name for the BigUser you can use the South rename-field utility (South can't auto-detect field renames so make sure to read the docs).
If you don't have any data in the database then you can simply implement the class above and drop it into your current models.
If you need help writing data-migrations you'll have to post a model or two.
Since you need something that's a "drop-in" replacement for User
you'll need two more steps:
First we need to create a custom authentication back-end, this makes sure that any authentication requests go to your new model and that request.user
returns BigUser
and not User
. Just cut and paste this snippet into a file called auth_backend.py in the same directory as settings.py:
from django.conf import settings
from django.contrib.auth.backends import ModelBackend
from django.core.exceptions import ImproperlyConfigured
from django.db.models import get_model
class CustomUserModelBackend(ModelBackend):
def authenticate(self, username=None, password=None):
try:
user = self.user_class.objects.get(username=username)
if user.check_password(password):
return user
except self.user_class.DoesNotExist:
return None
def get_user(self, user_id):
try:
return self.user_class.objects.get(pk=user_id)
except self.user_class.DoesNotExist:
return None
@property
def user_class(self):
if not hasattr(self, '_user_class'):
self._user_class = get_model(*settings.CUSTOM_USER_MODEL.split('.', 2))
if not self._user_class:
raise ImproperlyConfigured('Could not get custom user model')
return self._user_class
Then in your settings.py file you need to add this back-end and set the custom user model setting ... like so:
AUTHENTICATION_BACKENDS = (
'auth_backends.CustomUserModelBackend',
)
...
CUSTOM_USER_MODEL = 'your-app-name.BigUser'
This last section of code comes from another website describing subclassing the User model.
Now all you need to do to "drop-in" in the rest of your code is to replace all of the from django.contrib.auth.models import User
with from your-app-name import BigUser as User
. By doing this you wont have to update any references of User
with BigUser
I am weighing the option of changing the code of django.contrib.auth.models.user to include an id field as BigIntegerField primary key.
Seems to me to be the best way to go.
(I am ready to migrate the data manually via sql)
精彩评论