前回はApacheのドキュメントルート以外でDjangoを動かしました。
今回はDjangoのサーバー機能を使ってユーザー認証機能のテストをします。
ユーザー認証は会員専用ページとかユーザー専用のページを作るには必須事項です。
Djangoは認証のややこしい手間を省いてそういったページを作るにはうってつけのツールです。
ユーザー認証のサンプルはこちらのサイトを参考にさせていただきました。
Djangoでは標準でユーザー認証機能が付いています。
[アドレス]/admin
にアクセスするとデフォルトで既にユーザー管理サイトが存在しています。
ちなみに、前回の方法でapache2からアクセスするとスタイルシートが読み込まれていない場合はこのようになります↓
プロジェクトのmanage.pyのあるディレクトリから
$ python3 manage.py runserver 0:8000
としてDjangoのサーバーで起動しましょう。
しかしこのままではユーザー登録をしていないので何を入力してもログインできません。
まずは「管理者」を登録する必要があります。
manage.pyのあるディレクトリから以下を実行します。
@raspberrypi:/home/django/draemon $ sudo python3 manage.py createsuperuser
ユーザー名 (leave blank to use 'root'): draemon
メールアドレス: dradra@draemon.jp
Password:
Password (again):
このパスワードは短すぎます。最低 8 文字以上必要です。
このパスワードは一般的すぎます。
このパスワードは数字しか使われていません。
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.
パスワード(1234)は短すぎるとか数字だけとか怒られてしまいましたがテスト用なのでy(yes)としてadmin登録しました。
登録してからログインするとログイン後のページが表示されるはずです。
このようなエラーが出たら
データベースのアクセス権限エラーのようです。
[ データベース ] と [ 親ディレクトリ ]をその他ユーザーで扱えるようにしましょう。
ちなみに、Raspbianで使っているapache2のユーザー名はデフォルト「www-data」でした。CentOSの場合は「Apache」です。
Djangoからデフォルトで提供されているユーザー認証機能は
- ログイン
- ログアウト
- パスワード管理(再設定)
の3つだけのようです。
それぞれに対応したURLパターンも決められているようです。
accounts/login/ [name='login']
accounts/logout/ [name='logout']
accounts/password_change/ [name='password_change']
accounts/password_change/done/ [name='password_change_done']
accounts/password_reset/ [name='password_reset']
accounts/password_reset/done/ [name='password_reset_done']
accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm']
accounts/reset/done/ [name='password_reset_complete']
ところで、一番最初に欲しい「ユーザーの新規登録機能」は提供されていないようです。これは「登録っつったて名前やIDやメールアドレスや住所や各種管理番号や用途によっていろいろあるから自由に作ってね」ということでしょう。サンプルとして動かすには少し面倒そうです。
何はともあれ、機能を実装するにはまずはログイン・ログアウトの設定をします。
/home/django/draemon $ sudo nano draemon/urls.py
で、pathにaccounts/を追加します。
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', include('hello.urls')),
path('accounts/', include('django.contrib.auth.urls')),
]
これでログイン/ログアウト関連のビューが今から作るaccountsアプリとして有効化されます。
/home/django/draemon $ sudo nano draemon/settings.py
settings.pyにログイン後のリダイレクトアドレスを設定します。
LOGIN_REDIRECT_URL = '/hello'
設定しない場合はデフォルトで/profileページに飛びます。これはオプション機能のようです。
helloアプリケーションは以前に作ったコレです。
ユーザー認証用にaccountsというアプリケーションを作ります。
/home/django/draemon $ sudo python3 manage.py startapp accounts
アプリケーションをプロジェクトに登録します。
/home/django/draemon $ sudo nano draemon/settings.py
INSTALLED_APPS = [
'hello',
'accounts.apps.AccountsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
アプリケーションのurls.pyを作ります。
/home/django/draemon $ sudo nano accounts/urls.py
#!/usr/bin/python3
#coding:utf-8
from django.conf.urls import url
from django.urls import path
from . import viewsapp_name='accounts'
urlpatterns = [
path('signup/', views.SignUpView.as_view(),name="signup"),
]
アプリケーションのurls.pyに連携させるようにプロジェクトのurls.pyも編集します。
/home/django/draemon $ sudo nano draemon/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', include('hello.urls')),path('accounts/', include('accounts.urls')),
path('accounts/', include('django.contrib.auth.urls')),
]
accountsアプリケーションのviews.pyを編集します。
/home/django/draemon $ sudo nano accounts/views.py
from django.shortcuts import render
from django.contrib.auth.forms import UserCreationForm
from django.urls import reverse_lazy
from django.views import genericclass SignUpView(generic.CreateView):
form_class = UserCreationForm
success_url = reverse_lazy('login')
template_name = 'accounts/signup.html'
テンプレートをaccountsアプリケーションの中に作ります。
/home/django/draemon $ sudo nano accounts/templates/accounts/signup.html
{% extends 'base.html' %}
{% block content %}
<h1>Sign up</h1>
<section class="common-form">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="submit">Sign up</button>
</form>
</section>
{% endblock %}
これで一度サーバーを起動させて/signupしようとしたらエラーが出ました。
どうやらデフォルトのhtmlが読めないらしいです。
よくわかりませんが、ベースのtemplateが読み込めないエラーが出たのでdjangoのプロジェクト直下にtemplatesディレクトリを作成し、必要なテンプレートをDjangoからコピーしました。
まずはデフォルトのテンプレートが格納されているディレクトリを調べます
$ python3 -c "import django; print(django.__path__)"
['/usr/local/lib/python3.5/dist-packages/django']
ここにtemplateディレクトリがあるので全てコピー
sudo cp -r /usr/local/lib/python3.5/dist-packages/django/template /home/django/draemon
すると読み込んでくれました。(強引な方法なのかもしれない)
これでサインアップページが出来ました。
Djangoでログインできた登録ユーザーしか見られないページを作るのは簡単です。
views関数の前に@login_requiredを付け加えるだけ。
from django.contrib.auth.decorators import login_required
@login_required
def hello_world(request):
これでログインしていない状態でアプリケーションアドレスへアクセスすると自動でログイン画面に飛ばされます。
ログインした状態でアプリケーションへアクセスすると通常の画面が表示されます。
会員専用ページですね。
これらの機能を自前で作ろうとするとクッキーやらhiddenやらのお勉強が結構な手間なので非常に有り難い機能です。 (bottleには無い)
じゃあ、ユーザー専用ページは?
試しに、id、ユーザー名、パスワードを出力させてみました。
from django.http.response import HttpResponse
import datetime
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User@login_required
def hello_world(request):
userid = str(request.user.id)
username = request.user.username
password = request.user.password
return HttpResponse("<h1>Hello World!</h1>" + userid + ':' +username+':'+password)
パスワードにはsha256というビットコインでも使われている強力なhash値が使われており、生のデータは保存されていないので安心できそうです。
これでユーザー情報を元にログインユーザーの専用ページを表示させるというシステムが組めますね。
<追記>毎回ログイン時に表示される「Django管理サイト」の名前を変更する方法↓
<参考ページ>
会員登録機能
Djangoで、会員登録機能を自作する - naritoブログ
Django2 でユーザー認証(ログイン認証)を実装するチュートリアル
データベースエラー
ユーザー情報
django.contrib.auth | Django documentation | Django