はじめに
前回の内容から大分、間が空いてしまいましたがDjangoによるWeb開発を進めていきたいと思います。
今回はDjangoにログイン認証の画面を作成する所までを進めていきたいと思います。
アプリケーションを作成する
DjangoではTOPディレクトリに作成したプロジェクトの配下となるアプリケーションを作成する事で、独立した操作を行えるアプリケーションを作成する事ができます。プロジェクトはそのアプリケーションを一つにまとめたものです。
サブモジュールとしてsample_project/作成するアプリケーション名
とすることもできますが、今回はTOPディレクトリに置くことにします。
アプリケーションを作成するには、 manage.py と同じディレクトリに入って、以下のコマンドを実行します。
% python manage.py startapp polls
pollsのディレクトリ構成は以下のようになります。
% ls -al polls
total 21
drwxr-xr-x 3 himrock922 himrock922 9 11月 4 18:18 .
drwxr-xr-x 6 himrock922 himrock922 12 11月 4 18:18 ..
-rw-r--r-- 1 himrock922 himrock922 0 11月 4 18:18 __init__.py
-rw-r--r-- 1 himrock922 himrock922 63 11月 4 18:18 admin.py
-rw-r--r-- 1 himrock922 himrock922 91 11月 4 18:18 apps.py
drwxr-xr-x 2 himrock922 himrock922 3 11月 4 18:18 migrations
-rw-r--r-- 1 himrock922 himrock922 57 11月 4 18:18 models.py
-rw-r--r-- 1 himrock922 himrock922 60 11月 4 18:18 tests.py
-rw-r--r-- 1 himrock922 himrock922 63 11月 4 18:18 views.py
viewの作成
Djangoで最も単純なビューページを書いていきます。
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the polls index.")
単純な文字出力を行うviewを呼ぶために、URLに対応づけしてあげる必要があります。
そのためには、URLconf
が必要となります。
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
views.pyのindexメソッドを呼び出し、パス名をindex
として、紐付けさせます。
次に、ルートのURLConfにaccounts.urlsモジュールを読み込ませます。
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]
include()
関数は他のURLConfへの参照をする事ができます。
以上で簡単なURLのPathを作成する事ができました。
この内容に沿った形でログイン認証を行うページを作ろうと思ったのですが、実は既にDjangoには認証システムが用意されています。
Djangoの認証システムを使ってログイン認証システムを作る
こちらにきめ細かな仕様が載っているのですが、情報量が多すぎるので読むのが少し大変でした汗。ひとまず、認証を実現する機能として必要なメソッドやモデルが既に用意されているdjango.contrib.auth
があるのでstartappで作る必要がない模様です。
これだけだと、分かりにくかったのでもう一つ参考文献を。
Django Login/Logout Tutorial (Part 1)
認証用のviewは実装されているが対応するテンプレートはサポートしていないため、各自で実装すること、またサインアップのメソッドは用意されていないため、こちらも各自で書く必要があります。いずれにせよ、startappでアプリケーションを作成する必要がないので、上のDjango Login/Logout Tutorial (Part 1)
を参考にログイン認証を作っていきます。
% rm -rf polls
Auth App
Djangoプロジェクトを構築した時に自動的にauth
アプリケーションがインストールされています。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
authアプリケーションを使うために、urls.pyにaccounts配下のパスとauth.urlsのパターンを紐付けさせます。
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
]
authアプリケーションをincludeすると、以下の認証ビューが提供されます。
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']
ついでにこの際時刻設定と日本語設定、およびsqlite3からpostgresqlを使う様に設定します。
% sudo pkg install postgresql10-server-10.5 postgresql10-contrib-10.5
% sudo vim /etc/login.conf
postgres:\
:lang=en_US.UTF-8:\
:setenv=LC_COLLATE=C:\
:tc=default:
% sudo vim /etc/rc.conf
postgresql_class="postgres"
postgresql_enable="YES"
% sudo service postgresql initdb
% sudo service postgresql start
$ sudo su - postgres
$ createdb mydb
$ createuser -P
$ psql
$ GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;
% pip install psycopg2
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'mydb',
'USER': 'myuser',
'PASSWORD': 'mypass',
'HOST': 'localhost',
'PORT': '',
}
}
(中略)
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
ログインページを作成する
ログインページを作ります。authはデフォルトでregistration配下のテンプレートフォルダを読み込みます。registrationディレクトリを作成し、loginテンプレートとしてlogin.htmlを作成します。
% mkdir -p templates/registration
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% csrf_token %}でCSRFトークンを発行でき、
{{ form.as_p }}`でログインフォームを作成できます。
続いてDjangoがtemplates
ディレクトリを見つけられるように、settings.pyを修正します。
また、ログイン成功後のリダイレクトページを指定するためにLOGIN_REDIRECT_URL
を追加します。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
LOGIN_REDIRECT_URL = '/'
ユーザーを作成後、Djangoを再起動すると http://127.0.0.1:8080/accounts/login においてログインページが表示されます。
ログインできるようにユーザー作成を行いましょう。
% python3.7 manage.py migrate (git)-[feature/add_login]
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying sessions.0001_initial... OK
% python manage.py createsuperuser
ユーザー名 (leave blank to use '*********'):
メールアドレス: ********
Password:
Password (again):
Superuser created successfully.
以上で、作成したユーザーでログインする事ができるのですが、ログイン成功後のリダイレクトページをまだ作っていないため、レスポンスは404が返ってきます。
次にindexのページを作ってあげましょう。
indexページの作成
indexのページと全ページ共通のrenderページとしてapplication.htmlを作成します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>{% block title %}Django Auth Tutorial{% endblock %}</title>
</head>
<body>
<main>
{% block content %}
{% endblock %}
</main>
</body>
</html>
{% extends 'application.html' %}
{% block title %}Home{% endblock %}
{% block content %}
{% if user.is_authenticated %}
Hi {{ user.username }}!
{% else %}
<p>You are not logged in</p>
<a href="{% url 'login' %}">login</a>
{% endif %}
{% endblock %}
また、それに伴いlogin.htmlをapplication.htmlを読み込むように修正します。
{% extends 'application.html' %}
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endblock %}
次にurls.pyを修正し、/のurlパターンの際に読み込むTemplateを指定してあげます。
from django.contrib import admin
from django.urls import include, path
from django.views.generic.base import TemplateView
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
path('', TemplateView.as_view(template_name='index.html'), name='index'),
]
最後にLOGIN_REDIRECT_URLを/
からindex
に変更します。
LOGIN_REDIRECT_URL = 'index'
以上でログイン遷移のページまで作成することができました。
あとがき
もうちょいペースアップします。