Django1.4のユーザ認証のいろは

Django1.4の認証機能を使ってユーザ登録とユーザログインを行うWebアプリをチュートリアル形式でまとめます。
(Python 2.7.2)

今回は、Userクラスをどう使うかを示すだけなので、重複チェックと暗号化は無視しているので、そのままでは本番運用には使えません。

今回作る画面は次の3つです。
・ホーム画面 (ログインするかユーザ登録画面へ飛ぶかを選択)
・ユーザ登録画面
・ログイン完了後の画面


1. Djangoプロジェクト(authprj)を作成

django-admin.py startproject authprj

(注)出来上がったディレクトリ構造を見ての通り、settings.pyがプロジェクトルート直下ではなく、プロジェクトルート直下の更に下のプロジェクトディレクトリ内にできています。

プロジェクト作成直後のディレクトリ構造
authprj
├── authprj
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

2. Djangoアプリケーション(authapp)を作成

cd authprj
django-admin.py startapp authapp

アプリケーション作成直後のディレクトリ構造
authprj
├── authapp
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── authprj
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

アプリケーションができたら、authprj/authprj/settigs.pyのINSTALLED_APPSタプルに下記を記入することでプロジェクトにアプリを組み込みます。

'authapp',


3. setting.pyの編集
今回はパッと済ませたいので、sqlite3を選びます。
authprj/authprj/settings.pyのDATABASESディクショナリの、ENGINEとNAMEを以下の値にします。

'ENGINE': 'django.db.backends.sqlite3',
'NAME: 'authprj.db'

書き換えたら下記コマンドでDBを作ります。(今はauthprj直下にいるはずです)

python manage.py syncdb

syncdbを初めて実行すると、管理者ユーザを作るかどうか尋ねられます。
今回は不要なので、noを選んで次のステップに進みます。


すると、authprj内にauthprj.dbファイルができます。


4. templateディレクトリの指定
今回は画面は3つしか作らないので、htmlファイルはauthappディレクトリに直置きします。
なので、authprj/authprj/settings.pyのTEMPLATE_DIRSタプル内にauthprj/authappディレクトリのフルパスを追加しておいてください。


5. HTMLファイルを作成
authprj/authapp内に
・index.html   (ログインするかユーザ登録画面へ飛ぶかを選択する画面)
・register.html (ユーザ登録画面
・home.html  (ログイン完了後の画面)
を事前に作ります。


● index.html

<!DOCTYPE html>
<head><meta charset="UTF-8"></head>
<body>
  <form method="post" action="/login">{% csrf_token %}
    User ID: <input type="text" name="user_id" />
    <br />
    Password: <input type="password" name="password" />
    <br />
    <input type="submit" value="login" />
  </form>
  <br />
  <a href="register">Register</a>
</body>
</html>


● register.html

<!DOCTYPE html>
<head><meta charset="UTF-8"></head>
<body>
  <form method="post" action="create_user">{% csrf_token %}
    User ID: <input type="text" name="user_id" />
    <br />
    Password: <input type="password" name="password" />
    <br /> 
    <input type="submit" value="Register" /> 
  </form> 
</body> 
</html>


● home.html

<!DOCTYPE html>
<head><meta charset="UTF-8"></head>
<body>
  <h1>Hello World!</h1>
  <h2>You're logging</h2>
</body>
</html>

(注)Django1.3以降でPOSTメソッドを使うときは{% csrf_token %}の記述が必要です。


6. viewの定義
今回は、以下5つのviewを定義します。viewはauthprj/authapp/views.pyを編集します。

・index … index.htmlに対応
・register … register.htmlに対応
・create_user … create_user(register.htmlのformで指定したactionのURL)に対応
・login … login(index.htmlのformで指定したactionのURL)に対応
・home … home.htmlに対応


● views.py

from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from django.contrib.auth import login as auth_login
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.shortcuts import redirect

def index(request):
    return render_to_response('index.html', {},
            context_instance=RequestContext(request))


def register(request):
    return render_to_response('register.html', {},
            context_instance=RequestContext(request))


def create_user(request):
    user_id = request.POST['user_id']
    password = request.POST['password']

    new_user = User.objects.create_user(user_id, None, password)
    new_user.save()

    return redirect('/')


def login(request):
    user_id = request.POST['user_id']
    password = request.POST['password']
    user = authenticate(username=user_id, password=password)
    if user is not None:
        if user.is_active:
            auth_login(request, user)
            return redirect('/home')
        else:
            return redirect('/')
    else:
        return redirect('/')

def home(request);
    return render_to_response('home.html', {})


(注)Django1.3以降では、POSTメソッドを使うときには、htmlファイル内のformタグの後ろに{% csrf_token %}を追加すると同時に、それに対応するviewのrender_to_responseにcontext_instance=RequestContext(request)を記述しておく必要があります。


7. URLルーティングの追加
authprj/authprj/urls.pyにviewに対応するURLルーティングを追加します。


● authprj/authprj/urls.py

from django.conf.urls import patterns, include, url

urlpatterns = patterns('',
    url(r'^$', 'authapp.views.index'),
    url(r'^register$', 'authapp.views.register'),
    url(r'^create_user$', 'authapp.views.create_user'),
    url(r'^login$', 'authapp.views.login'),
    url(r'^home$', 'authapp.views.home'),
)


8. 開発環境サーバの起動とテスト
ターミナルでauthprj直下(1個目)に移動して次のコマンドで開発環境サーバの起動を行います。

python manage.py runserver

・ブラウザを開き、http://127.0.0.1:8000にアクセスします。
・Registerと書かれたリンクをクリックして、User IDとPasswordにそれぞれ任意(ここではUser ID=spamとPasswordにeggsを例として入力します)の文字列を入力し、Registerボタンをクリックします。
・再び http://127.0.0.1:8000 にリダイレクトされるので、登録したUser IDとPasswordを入力してloginボタンをクリックします。
http://127.0.0.1:8000/homeのURLにリダイレクトされ、「Hello World! You're logging」と表示された画面が表示されているはずです。


9. Userモデルの登録内容を確認
今回はsqlite3を使っているので、authprj/authprj.dbに保存されています。authprj.dbの内容を確認するにはターミナル内で次のコマンドを打って確認します。
※ コマンド入力する箇所を青文字で表示しています。

sqlite3 authprj.db
SQLite version 3.7.12 2012-04-03 19:43:07
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .tables
auth_group auth_user_user_permissions
auth_group_permissions django_content_type
auth_permission django_session
auth_user django_site
auth_user_groups
sqlite> select * from auth_user;
select * from auth_user;
1|spam||||pbkdf2_sha256$10000$3QeATIiTfI1T$H9CaKwAB5J3uK2cHcIt87Rp4w7hXVxUFPzOV5KVc/uk=|0|1|0|2012-08-12 05:45:49.148236|2012-08-12 05:39:50.230669
sqlite> .exit


実際に使うときは、Userクラスを拡張したモデルを書いたり、デコレーターでログイン必須のビューを定義したり、ログアウト後のリダイレクト、重複チェック、ヴァリデーション、フォームなどを組み合わせて使いますが、それ以前のユーザ認証の基本を試すためのチュートリアルとして、是非参考にしてみてください。