はじめに
この記事はDjango Advent Calendar 2020 14日目の記事です。
頑張れば、何かがあるって、信じてる。nikkieです。
2020年はPyCon JPスタッフ活動の中で、力を付けたくてDjangoアプリを作りました。
Slackアカウントでアプリにログインする機能を実装する際に、素振り不足を理由にdjango-allauthの採用を見送りました。
これがちょっとした心残りとなっており、年内に解消すべくアドベントカレンダーの締切駆動でdjango-allauth
を触ることにしました。
目次
- はじめに
- 目次
- 経緯:積み残したdjango-allauth
- 開発環境
- 素振り1:『現場で使えるDjangoの教科書 実践編』に沿ってGitHubアカウントでログイン
- 素振り2:Slackアカウントでもログイン
- account_loginを経由せず、homeから直接ログインできるようにする
- 素振りしてみて
- 補足:django-environ
経緯:積み残したdjango-allauth
※8月のPyCon JPで話した内容1と重なります。
PyCon JPスタッフ活動の中で、レビューに使うスタッフ内部用のWebアプリ2をDjangoで実装しました。
スタッフだけがログインできるように、PyCon JP Slackのアカウントを使ってログインする機能を実装しました(スライド31〜33)。
実装中はdjango-allauth
も候補にあったのですが、ドキュメントを見た感じすぐに使えるイメージがつかめず、別のパッケージを使いました。
「会期が終わった後に同じ実装をするならdjango-allauth
を試したい」と思っていたので、今回試しました。
今回の素振りのゴールは、簡易的なアプリでdjango-allauth
を使ってSlackアカウントログインを実装することです。
「レビューアプリにdjango-allauth
を導入できそうという感触を持てたらいいな」と取り組みました。
開発環境
django-allauth
がPython 3.8までだったので、3.8を選択しました。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14.6 BuildVersion: 18G4032 $ python -V Python 3.8.6 $ pip install Django==3.1.4 django-allauth==0.44.0 django-environ==0.4.5
Django Girls Tutorialに沿ったディレクトリ構成で今回の練習用アプリを実装しています。
DBはsqliteを使い、ローカルでのみ動かしました。
リポジトリはこちらです。
素振り1:『現場で使えるDjangoの教科書 実践編』に沿ってGitHubアカウントでログイン
参考にしたのは、akiyokoさんの『現場で使えるDjangoの教科書 実践編』。
django-allauth
はソーシャルアカウント連携だけではなく、allと名に負う通り、ログイン周り全般も面倒を見てくれます!
※ただし、今回はソーシャルアカウント連携に絞って見ていきます。
前提
前提として、以下の状態とします(Django Girls Tutorialベースです)。
# 前提:作業ディレクトリにいる $ python3.8 -m venv myvenv $ . myvenv/bin/activate # ... 上で挙げたパッケージをpip installする $ django-admin startproject mysite . # ... Django Girls Tutorialに沿って「設定変更」する(mysite/settings.pyを変更) $ python manage.py migrate
作業ディレクトリの状態
. ├── db.sqlite3 ├── manage.py ├── mysite └── myvenv
settings.py 変更(URL & テンプレート追加)
django-allauth
を使うために、まず mysite/settings.py を変更。
INSTALLED_APPS = [ # : すでにあるものの下に以下を追加 'django.contrib.sites', # django-allauthに必要 'allauth', 'allauth.account', 'allauth.socialaccount', 'allauth.socialaccount.providers.github', ] # ... 途中を省略 ... 以下は一番下に追加 ################## # Authentication # ################## SITE_ID = 1 LOGIN_REDIRECT_URL = "home" ACCOUNT_LOGOUT_REDIRECT_URL = "account_login"
django-allauth
をインストールしたので、migrate
が必要です。
続いて、以下の2つのファイルを用意します。
mysite/urls.py3
urlpatterns = [ path('admin/', admin.site.urls), # 以下2行を追加 path('', TemplateView.as_view(template_name='home.html'), name='home'), path('accounts/', include('allauth.urls')), ]
templates/home.html4(新規作成)
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>ホーム</title> </head> <body> <h2>すごいアプリ</h2> {% if user.is_authenticated %} ようこそ {{ user.get_username }} さん <p><a href="{% url 'account_logout' %}">ログアウト</a></p> {% else %} <p><a href="{% url 'account_login' %}">ログイン</a></p> {% endif %} </body> </html>
GitHub OAuth App作成
以下を参考にしました。
Authorization callback URLにはhttp://127.0.0.1:8000/accounts/github/login/callback/
を設定。
Django Adminの操作
createsuperuser
してからDjango Adminにログインします。
「外部アカウント」の「Social applications」から追加していきます。
以上で、GitHubアカウントでログインできるようになります。
127.0.0.1:8000/(templates/home.htmlの表示)
「ログイン」をクリックするとログインページを表示(ビューとテンプレートはdjango-allauth
が用意)
127.0.0.1:8000/accounts/login/
GitHubで初回ログイン(認可を求められる)※同じブラウザですでにGitHubにログインしています
ログイン状態で 127.0.0.1:8000/ に戻る
素振り2:Slackアカウントでもログイン
半年前にやりたかったSlackアカウントでのログインに挑戦してみます。
- Slack App作成
- Django Adminの操作の代わりに
mysite/settings.py
に設定追加
Slack App作成
SlackはWorkspaceごとにアカウントがありますが、ログインに使いたいアカウントのあるWorkspaceでAppを作ります。
「OAuth & Permissions」に以下を設定しています
- Redirect URLs
http://127.0.0.1:8000/accounts/slack/login/callback/
5
- Scopes > User Token Scopes
- 未設定だとAppのインストールができないと表示されました
- Slackのドキュメントによると
identity
が必要なようなので、identity.basic
を設定
mysite/settings.py
に設定追加
Django Adminで操作しなくても、mysite/settings.py
に設定を追加してもできるようです。
INSTALLED_APPS = [ # 省略。以下を追加 'allauth.socialaccount.providers.slack', ] # 省略 ################## # Authentication # ################## # 省略。一番下に以下を追加 SOCIALACCOUNT_PROVIDERS = { # GitHub用のSocial applicationを削除して以下でも動きます # "github": { # "APP": { # "client_id": env("GITHUB_OAUTH_CLIENT_ID"), # "secret": env("GITHUB_OAUTH_SECRET"), # } # }, "slack": { "APP": { "client_id": env("SLACK_OAUTH_CLIENT_ID"), "secret": env("SLACK_OAUTH_SECRET"), } }, }
127.0.0.1:8000/accounts/login/ にSlackアカウントでログインするためのリンクが追加されます!
リンクをクリックすると、Slackアカウントでのログインにあたり許可が求められます。
なお、今回はGitHubアカウントで連携してログインした後、http://127.0.0.1:8000/accounts/social/connections/ にアクセスしてSlackアカウントも連携しました。
なので、SlackアカウントでログインするとGitHubアカウントでログインしたときと同じように表示されます。
account_loginを経由せず、homeから直接ログインできるようにする
ここまでで作ったアプリは、homeからaccount_login(django-allauth
が用意するログインページ)に遷移してログインします。
templates/home.html(新規作成)
<p><a href="{% url 'account_login' %}">ログイン</a></p>
homeから直接ログインできるように、ソースコードを見ていじってみました(もっといいやり方をご存知の方いたら教えていただけると嬉しいです)。
<!-- <p><a href="{% url 'account_login' %}">ログイン</a></p> --> お持ちの外部アカウントでログインをどうぞ <ul class="socialaccount_providers"> {% include "socialaccount/snippets/provider_list.html" with process="login" %} </ul>
参考にしたのは、allauth/templates/account/login.html。6
ソースコードを少し見たところ、settings.pyで有効にしたprovider(今回はGitHubとSlack)について、ログインに使うリンクが作られる挙動のようでした。
- allauth/templates/socialaccount/snippets/provider_list.html(login.htmlでincludeしているコード)
- allauth/socialaccount/templatetags/socialaccount.py(provider_list.htmlで使っているtemplatetag。
get_providers
などが実装されている)
素振りしてみて
素振りする前は、キャッチアップが大変そうという印象のdjango-allauth
でしたが、akiyokoさんの本を経由してドキュメントを読み、「ソースコード周りはsettings.pyの設定だけでソーシャルアカウント連携が実装できる!便利」と印象は大きく変わりました。
今回の素振りを元にやってみたい項目は以下です(年内にできたらいいな)。
django-allauth
を使うと、ソーシャルアカウント連携は設定が大部分という感触を得ました。
来年作るDjangoアプリでは積極的に使っていけそうです!
補足:django-environ
先のコードで登場した env("SLACK_OAUTH_CLIENT_ID")
などについて補足します。
OAuthの設定に必要なClient IDやSecret、DjangoのSECRET_KEY
などは環境変数に設定していますが、コードではdjango-environ
で扱っています。
これも知ったのはakiyokoさんの本(実践編)です。
使い方は簡単で、ドキュメントの冒頭のコードが参考になります。
mysite/settings.py
import environ env = environ.Env(DEBUG=(bool, False)) environ.Env.read_env(env_file=str(BASE_DIR / ".env"))
今回はリポジトリのルート(BASE_DIR
)に.env
ファイルを置きました。
.env
ファイルを示すpathlib.Path
が受け取れないようなので、文字列に変換して渡しています。
環境変数を.env
ファイルでまとめて管理でき、便利です。
.env
ファイルのイメージ
DEBUG=on SECRET_KEY=very_very_secret_key SLACK_OAUTH_CLIENT_ID=2****************4 SLACK_OAUTH_SECRET=hi_mi_tsu
-
嬉しいお言葉もいただきました。ありがとうございます。「いつ作ってるんあろうと思うぐらい作りこまれてまして」ref: まったりLog残し - PyCon JP 2020に参加してきました↩
-
django.views.generic.TemplateView
はakiyokoさんの『基礎編』の教科書に解説があります↩ -
リポジトリルートの
templates
ディレクトリからテンプレートを探せるように、mysite/settings.py
のTEMPLATES
のDIRS
にBASE_DIR / "templates"
を追加する必要があります↩ -
ref: https://django-allauth.readthedocs.io/en/latest/providers.html#slack↩
-
urls.pyを見たところ、account_loginという名前のパスに対応するビューはLoginViewでした。settings.pyで設定をしていない場合、
account/login.html
という名前のテンプレートが使われるようでした↩