Django 1.5のカスタムユーザーモデルとdjango-registration その2

django 1.5でプロジェクト作って、カスタムユーザーモデルを定義してみる。


apps.models.py

from django.contrib.auth.models import AbstractBaseUser
from django.db import models
from django.utils.translation import ugettext_lazy as _


class MyUser(AbstractBaseUser):
    email = models.EmailField(_('e-mail address'), unique=True, db_index=True)
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

emailをログインに使うようにしてみる


settings.pyにAUTH_USER_MODELを定義

AUTH_USER_MODEL = 'apps.MyUser'


django-registraionのfork版をINSTALLED_APPSに追加
settings.py

INSTALLED_APPS += ('registration',)


何も考えずにurls.pyにaccounts周りのurlを追加

urlpatterns += patterns('',
                        url(r'^accounts/', include('registration.backends.default.urls')),
)


再びsettings.pyにユーザー登録で使用されるメール周りの設定を追加。
手っ取り早くgmailで送信

ACCOUNT_ACTIVATION_DAYS = 7

EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'xxxxxxxxxxxx@gmail.com'  # 使用するgmailアカウント
EMAIL_HOST_PASSWORD = 'xxxxxxxxxxx'     # 使用するgmailアカウントのパスワード
EMAIL_PORT = 587

LOGIN_REDIRECT_URL = '/'


テンプレート忘れてた。
そのまま使えるかわからないけど、パッケージで用意されているものを入れてみる

pip install django-registration-defaults

settings.py

INSTALLED_APPS += ('registration',
                   'registration_defaults')


syncdbしてみる。

superuser作るところでエラー。
AttributeError: 'Manager' object has no attribute 'get_by_natural_key'

Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table django_admin_log
Creating table apps_myuser
Creating table registration_registrationprofile

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
E-mail address: xxxxxxxxxxxxxx@gmail.com
AttributeError: 'Manager' object has no attribute 'get_by_natural_key'


カスタムユーザーモデルを使う場合は、Managerも定義しないといけないようだ。

You should also define a custom manager for your User model. If your User model defines username and email fields the same as Django’s default User, you can just install Django’s UserManager; however, if your User model defines different fields, you will need to define a custom manager that extends BaseUserManager providing two additional methods:
Customizing authentication in Django | Django documentation | Django


apps.models.py

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
from django.utils.translation import ugettext_lazy as _


class MyUserManager(BaseUserManager):

    def create_user(self, email, password=None):
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(email=BaseUserManager.normalize_email(email))
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password):
        u = self.create_user(email, password=password)
        u.is_admin = True
        u.save(using=self._db)
        return u


class MyUser(AbstractBaseUser):
    email = models.EmailField(_('e-mail address'), unique=True, db_index=True)
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)

    objects = MyUserManager()
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []


これでユーザー登録は通った。


起動して/accounts/loginをみてみる


今度はregistration-defaultsのテンプレートのurl関数でエラーに。1.5で変わったんでしたね。

NoReverseMatch at /accounts/login/
'url' requires a non-empty first argument. The syntax changed in Django 1.5, see the docs.


/accounts/loginの場合、registration/login.htmlの以下の箇所でエラーになる。

<form method="post" action="{% url django.contrib.auth.views.login %}">{% csrf_token %}


INSTALLED_APPSからregistration-defaultsは外して、テンプレートをプロジェクトのTEMPLATE_DIRにコピーして修正する。
urlを使ってるところは全部修正しないといけない。


これでとりあえずログインは見れるようになった。
ちゃんとemailをログインに使うようになってる。



ログインできること、不正なパラメータでログイン失敗すること、/accounts/logoutでログアウトできることを確認できた。