GoogleAppEngine用フレームワーク「Kay」で認証用ユーザーに属性を追加する

GoogleAppEngine用フレームワーク「Kay」のデータストア認証で使用するDatastoreUserを継承して属性を追加する方法。

データストア認証で使用するクラスに属性を追加するには、DatastoreUserを継承したクラスを作成します。

総論

ポイントとしては、

  • kay.auth.models.DatastoreUserを継承したクラスを作成する。
  • settings.AUTH_USER_MODELにkay.auth.models.DatastoreUserを継承したクラスを指定する。
  • 登録するときはcreate_new_user()関数を使う。追加した属性はキーワード引数で指定する。

その他は、Kayのドキュメント「1. Kay チュートリアル」「9. 認証の設定」と同じようなものです。

プロジェクトの作成

プロジェクトを作成します。

$ python kay/manage.py startproject myproject
$ cd myproject
$ python manage.py startapp myapp

次のようにファイルが作成されました。

myproject
|-- kay/
|-- myapp/
|-- app.yaml
|-- favicon.ico
|-- manage.py
|-- settings.py
`-- urls.py

settings.pyを編集して、myappを登録します。

settings.py

INSTALLED_APPS = (
    'myapp',
)

APP_MOUNT_POINTS = {
    'myapp': '/',
}

認証用ミドルウェアを有効にする

settings.MIDDLEWARE_CLASSES に kay.auth.middleware.AuthenticationMiddleware を追加し、認証機構を有効にします。

settings.py

MIDDLEWARE_CLASSES = (
    'kay.auth.middleware.AuthenticationMiddleware',
)

ログインボックスを使用するために、settings.INSTALLED_APPS に kay.auth を追加します。
また、settings.CONTEXT_PROCESSORSに kay.auth.context_processors.login_box を追加します。

INSTALLED_APPS = (
    'kay.auth',
    'myapp',
)

CONTEXT_PROCESSORS = (
    …
    'kay.auth.context_processors.login_box',
)

データストア認証を有効にする

データストア認証に必要なSessionMiddlewareを有効にするため、settings.MIDDLEWARE_CLASSES に kay.auth.middleware.SessionMiddleware を追加します。

settings.py

MIDDLEWARE_CLASSES = (
    'kay.sessions.middleware.SessionMiddleware',
    'kay.auth.middleware.AuthenticationMiddleware',
)

settigns.AUTH_USER_BACKEND に kay.auth.backends.datastore.DatastoreBackend を設定します。

DatastoreUserを継承したクラスMyUserを作成し、認証に使用するクラスとして設定します。

settings.py

AUTH_USER_BACKEND = 'kay.auth.backends.datastore.DatastoreBackend'
AUTH_USER_MODEL = 'myapp.MyUser'

認証用クラスを作成する

DatastoreUserを継承したクラスMyUserを作成します。
address属性を追加します。

myapp/models.py

# -*- coding: utf-8 -*-
from google.appengine.ext import db
from kay.auth.models import DatastoreUser

class MyUser(DatastoreUser):
    address = db.TextProperty(u'住所', required=True)

ユーザー登録フォームを作成する

ユーザー登録フォームを作成します。

パスワードの入力を確認するために、パスワードを再入力する入力欄を追加します。

myapp/views.py

from kay.utils import forms
from kay.utils.validators import ValidationError

class MyUserForm(forms.Form):
    user_name = forms.TextField(u'ユーザー名', required=True)
    password = forms.TextField(u'パスワード', required=True)
    password_confirm = forms.TextField(u'パスワードの再入力', required=True, widget=forms.PasswordInput)
    address = forms.TextField(u'住所', required=True)

    def context_validate(self, data):
        '''パスワードの再入力チェック'''
        if data['password'] != data['password_confirm']:
            raise ValidationError(u'パスワードが一致しません。')

ユーザーの入力処理を作成する

認証ユーザーを登録するときはcreate_new_user()関数を使用します。
モデルに追加した属性は、キーワード引数で指定することで、登録することができます。

create_new_user(form['user_name'], 
                password=form['password'], 
                address=form['address'])

db.Model.put()を使用して登録すると、ログインボックスからログインすることができません。

ユーザー名がすでに登録されているときはDuplicateKeyErrorが発生します。

try:
    create_new_user(…)
    msg = u'ユーザーを登録しました。'
except DuplicateKeyError:
    msg = u'既に同じユーザー名が登録されています。'

myapp/views.py

from kay.utils import forms
from kay.utils.validators import ValidationError
from kay.auth import (create_new_user, DuplicateKeyError)
import models

def index(request):
    form = MyUserForm()
    msg = u''
    if request.method == 'POST':
        if form.validate(request.form):
            try:
                create_new_user(form['user_name'], 
                                password=form['password'], 
                                address=form['address'])
                msg = u'ユーザーを登録しました。'
            except DuplicateKeyError:
                msg = u'既に同じユーザー名が登録されています。'
    return render_to_response('myapp/index.html',
                              {'form': form.as_widget(),
                               'msg': msg,
                               'users': models.MyUser.all()})

myapp/templates/index.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Top Page - myapp</title>
</head>
<body>

{% from "auth/macros.html" import render_loginbox with context %}
<div>
{% if request.user.is_anonymous() %}
  {{ render_loginbox() }}
{% else %}
   Hello {{ request.user }}! <a href="{{ create_logout_url() }}">ログアウト</a>
{% endif %}
</div>

<div>
  <p>{{ msg }}</p>
{{ form()|safe }}
</div>

<table>
  <tr><th>ユーザー名</th><th>住所</th></tr>
{% for user in users %}
  <tr><td>{{user.user_name}}</td><td>{{user.address}}</td></tr>
{% endfor %}
<table>

</body>
</html>

コメント

  1. とても参考になります。
    AUTH_USER_MODEL = ‘myapp.MyUser’
    これは
    AUTH_USER_MODEL = ‘myapp.models.MyUser’
    ですよね?

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください