Install theme

django.contrib.auth.models.Userを継承して拡張する

DjangoのUserモデルを拡張したいのでやってみた。
使用したDjangoのバージョンは1.3

継承用のアプリの作成

ここではaccountsというアプリ名に。

python manage.py startapp accounts

auth.models.Userを継承したモデルの作成

マネージャーも変更できるようにauth.models.UserManagerを継承したクラスに変更。
継承したUserモデルには電話番号のfieldを追加してみた。

from django.db import models
from django.contrib.auth.models import UserManager as AuthUserManger, User as AuthUser

class UserManager(AuthUserManger):
    pass

class User(AuthUser):
    tel = models.SlugField(verbose_name=u'電話番号', max_length=13, blank=True)
    #デフォルトのマネージャを変更
    objects = UserManager()

認証用バックエンドの作成

先ほど作成したUserモデルで認証できるようにする。

accounts.backends.py

from django.contrib.auth.backends import ModelBackend as Backend
from accounts.models import User

class ModelBackend(Backend):
    """
    accounts.models.Userのユーザー認証をするバックエンド
    """
    def authenticate(self, username=None, password=None):
        try:
            user = User.objects.get(username=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

authenticate関数と、get_user関数の戻り値を継承したUserへ変更した関数を作る。

settings.pyに認証バックエンドを設定

AUTHENTICATION_BACKENDS = (
    "accounts.backends.ModelBackend",
)

これでOK。 django.contrib.auth.middleware.AuthenticationMiddleware はbackendのauthenticate関数を内部で使用してるので特に変更する必要はなさそう。

せっかくなのでadminでも動くようにする。

django.contrib.auth.admin.UserAdminを継承して動くようにする。

UserAdmin内部で使用するフォームを修正

UserCreationFormとUserChangeFormの使用するmodelを継承したUserモデルに変更する下準備。

account.forms.py

from django.contrib.auth.forms import UserCreationForm as AuthUserCreationForm, UserChangeForm as AuthUserChangeForm
from accounts.models import User

class UserCreationForm(AuthUserCreationForm):
    class Meta:
        model=User

class UserChangeForm(AuthUserChangeForm):
    class Meta:
        model=User

作成したUserモデルをMetaクラスにセットしとく

admin.pyの作成

accounts.admin.py

from django.contrib import admin
from django.contrib.auth.models import User as AuthUser
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin

from accounts.models import User
from accounts.forms import UserCreationForm, UserChangeForm

class UserAdmin(AuthUserAdmin):
    #さっき作ったフォーム
    form = UserChangeForm
    #さっき作ったフォーム
    add_form = UserCreationForm
    #追加した電話番号を更新できるように。
    fieldsets = AuthUserAdmin.fieldsets + (('tel', {'fields': ('tel',)}),)

#djangoのデフォルトUserモデルをadminサイトで表示しないように
admin.site.unregister(AuthUser)
#継承して作ったadminフォームを登録
admin.site.register(User, UserAdmin)

adminサイトにDjangoデフォルトのUserモデルは邪魔なので表示しないようにした。別にしなくてもいい。

syncdb時のスーパーユーザー作成コマンドを変更する。

syncdbした時に、superuserを作成していなければDjangoは作成するか聞いてくる。
これを継承したUserモデルに変更する。

スーパーユーザーを作成するコマンドを作成

「createsuperaccount」っていうコマンドを作ることにする。
手っ取り早くコピーしてしまおう。

django.contrib.auth.management.commands.createsuperuser.py

こいつをaccountsディレクトリ以下に配備

accounts.management.commands.createsuperaccount.py

ファイル名はコマンド名になるので注意。
importするUserを変更したらコマンド完成

#from django.contrib.auth.models import User
from accounts.models import User

post_syncdbシグナルを変更

デフォルトのcreate_superuserコマンドを無効化して、作成したcreatesuperaccountコマンドを有効化するシグナルを作成する。

accounts.management

from django.contrib.auth import models as auth_app
from django.db.models import get_models, signals
from django.contrib.auth.management import create_superuser as auth_create_superuser
from accounts import models as accounts_app

def cruser(app, created_models, verbosity, **kwargs):
    from django.core.management import call_command

    if accounts_app.User in created_models and kwargs.get('interactive', True):
        msg = ("\nYou don't have any superusers defined.\nWould you like to create one "
            "now? (yes/no): ")
        confirm = raw_input(msg)
        while 1:
            if confirm not in ('yes', 'no'):
                confirm = raw_input('Please enter either "yes" or "no": ')
                continue
            if confirm == 'yes':
                call_command("createsuperaccount", interactive=True)
            break

# デフォルトのcreate_superuserコマンドを無効化
signals.post_syncdb.disconnect(auth_create_superuser,
    sender=auth_app, dispatch_uid = "django.contrib.auth.management.create_superuser")

# 作成したcreate_superuserコマンドを有効化
signals.post_syncdb.connect(cruser,
    sender=accounts_app, dispatch_uid = "accounts.management.create_superuser")

これでsyncdbコマンドをコールした時に継承したモデルのスーパーユーザーを作成するか聞いてくる。

See more
This post has 1 note
Tagged with django,
Posted at 5:01 PM 08 April 2011
  1. hyokonia posted this
Bookmark and Share