見出し画像

【Django】allauthを使って承認機能を実装 (新規登録・ログイン・ログアウト...ect)

【前提条件】
-----------------------------------------------------------------------------
djangoのインストールが完了しプロジェクトディレクトリとアプリケーションディレクトリの作成、setting.pyにアプリケーションの登録までが
完了していること
-----------------------------------------------------------------------------

【確認事項】
本記事では、pythonのバージョンが3.0.0以上の環境で開発しているので、
コマンドは全てpython3 manage.py〜の表記にしています。
バージョンに合わせてpython3 manage.py 〜 →python manage.py
に読み変えてください。

【参考】


1. カスタムユーザーモデルのモデルのアプリケーション作成

まずは、allauth関連の前にプロジェクトディレクトリを作成しておく。
もうすでに作ってたら不要。
もし作っていなければ下記にて作る。
(今回は、my_projectという名前にした)

$ django-admin startproject my_project


続いて、allauthを扱うための、新規のアプリケーションディレクトリを作成する。
今回は"accounts"という名前にする。
以下のコマンドを実行

$ python3 manage.py startapp accounts

"accounts"ディレクトリが作成されたことを確認したら、
setting.pyにアプリケーションの登録をする。

2. allauthのインストール

下記のコマンドでインストール

$ pip install django-allauth


3. ユーザー作成を担うメソッドを持ったクラスを実装

"accounts"ディレクトリの中のmodels.pyに下記のコードを追記。
UserManager, AbstractUserをインポートすることを忘れないように注意。

from django.contrib.auth.models import UserManager, AbstractUser

class CustomUserManager(UserManager):
    use_in_migrations = True
 
    def _create_user(self, email, username, password, **extra_fields):
        # create_user と create_superuser の共通処理
        if not email:
            raise ValueError('email must be set')
        if not username:
            raise ValueError('username must be set')
 
        user = self.model(email=email, username=username, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
 
        return user
 
    def create_user(self, username, email=None, password=None, **extra_fields):
 
        if not email:
            raise ValueError('email must be set')
        if not username:
            raise ValueError('username must be set')
 
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
 
        return self._create_user(email, username, password, **extra_fields)
 
    def create_superuser(self, username, email=None, password=None, **extra_fields):
 
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
 
        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
 
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')
 
        return self._create_user(email, username, password, **extra_fields)


4.  カスタムユーザーモデルに対応するクラスの作成

"accounts"ディレクトリの中のmodels.pyに下記のコードを追記。

class CustomUser(AbstractUser):
    objects = CustomUserManager()
 
    def __str__(self):
        return self.email

ユーザーモデルとして CustomUser クラスを利用することを settings.py に明記。

AUTH_USER_MODEL = 'accounts.CustomUser'

以上、ここまででカスタムユーザーの実装は完了。

5. マイグレーション

マイグレーションする


$ python3 manage.py makemigrations
$ python3 manage.py migrate

このような結果になればOK

python3 manage.py makemigrationsの結果↓

Migrations for 'accounts':
  accounts/migrations/0001_initial.py
    - Create model CustomUser

python3 manage.py migrateの結果↓

Operations to perform:
  Apply all migrations: accounts, admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0001_initial... 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 auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying accounts.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 sessions.0001_initial... OK


6. allauthを使うための設定をする

まずは、 allauth アプリをプロジェクトに組み込む。
setting.pyのINSTALLED_APPSに以下4つを追加。

・django.contrib.sites
・allauth
・allauth.account
・allauth.socialaccount

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'diary',
    'bootstrap4',
    'widget_tweaks',
    'accounts',
    'django.contrib.sites', # 追加
    'allauth', # 追加
    'allauth.account', # 追加
    'allauth.socialaccount', # 追加
]

また INSTALLED_APPS の下に、下記の一行を書き加える。

SITE_ID = 1

続いて、認証の設定を行う。
setting.pyに下記を追記。

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend', #デフォルトの認証基盤 
    'allauth.account.auth_backends.AuthenticationBackend' # メールアドレスとパスワードの両方を用いて認証するために必要
)

ACCOUNT_AUTHENTICATION_METHOD = 'email' # メールアドレス(とパスワードで)認証する
ACCOUNT_USERNAME_REQUIRED = True # サインアップ(ユーザー登録)の時にユーザーネームを尋ねる
ACCOUNT_EMAIL_REQUIRED = True # サインアップ(ユーザー登録)の時にメールアドレスを尋ねる
ACCOUNT_EMAIL_VERIFICATION = 'mandatory' # メール検証を必須とする

LOGIN_URL = '/account/login/' # ログインURLの設定
LOGIN_REDIRECT_URL = '/index/' # ログイン後のリダイレクト先
ACCOUNT_LOGOUT_REDIRECT_URL = '/account/login/' # ログアウト後のリダイレクト先

プロジェクトディレクトリの中のurls.pyを以下のように編集する。
includeをインポートすることを忘れずに。

from django.contrib import admin
from django.urls import path, include # includeをインポート

urlpatterns = [
    path('admin/', admin.site.urls),
    path('account/', include('allauth.urls')), # 追加
]

割重要なのが、以下のコマンドを実行すること。


$ python3 manage.py migrate sites 
$ python3 manage.py migrate

ここでまでで一応ログインの画面が表示できるようになってるはずなので
確認してみる。下記にアクセス。
http://127.0.0.1:8000/account/login/

画面が表示されて、設定できてることが確認できた。
ただ、英語表記になっている。
これは、setting.pyの言語設定を日本語にしていないから。
日本語にするには、setting.pyのLANGUAGE_CODE を
元々のen-usからjaに変更する

LANGUAGE_CODE = 'ja'

日本語になりました。

7.動作確認


続いて、新規登録を試してみる。
その前に、以下をsetting.pyに追加する。
これは、メール配信をコンソール常に返すという設定である。
ローカルで開発の場合、メールサーバーがないのでこれを書かないと
エラーが出てしまう。

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

では、下記にアクセスして各情報を入力し登録してみる
http://127.0.0.1:8000/account/signup/

下記のようにコンソール出力すれれば成功。

以上で、allauthによる承認機能の実装が完了。


〜おまけ〜


allauthで承認機能の実装はこれにて完了だが、
せっかくなので、ログイン後に特定のページにアクセスするように実装してみたいと思う。

アプリケーションディレクトリを作る


実際に承認機能付きのwebサービスを作る際、このアプリケーションディレクトリで開発していくことになる。今回はtest_appという名前で作ってみる。

$ python3 manage.py startapp test_app

test_appのディレクトリが作られたら、その直下にtemplateディレクトリを作る。ここにログイン後にアクセスするビュー(html)を作成する。
名前はなんでもいいが、今回はindex.htmlにする。
index.htmlの中を下記のように書く。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ログイン後トップ画面</title>
</head>
<body>

    <h1>ログイン後トップ画面</h1>
    <div>
               ようこそ<b>{{ user.get_username }}</b>さん
        </div>

</body>
</html>

続いてsetting.pyに下記を追加して

# Tepmpateフォルダへの絶対パスを定義
TEMPLATE_DIR = BASE_DIR / "test_app/Template"

"TEMPLATES ="の中を以下のように書き換える

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [TEMPLATE_DIR,],
        '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',
            ],
        },
    },
]

プロジェクトディレクトリのurls.pyに下記を追加

from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('account/', include('allauth.urls')), 
    path('index/',include('test_app.urls')),# 追加
]

test_appの中にurls.pyファイルを新しく作り、下記のように中身を編集

from django.urls import path
from . import views


urlpatterns = [
    path('', views.index, name='index'),
    path('post_blog', views.post_blog, name='post_blog'),
]

test_appの中のviews.pyを以下のように編集

from django.shortcuts import render
from django.http import HttpResponse


# Create your views here.
def index(request):

    return render(request,'index.html')

setting.pyの中の"LOGIN_REDIRECT_URL ="を確認
ここに書かれたURLがログイン後のリダイレクト先となる。
これまでの設定で/indexにアクセスされたらindex.htmlを返すようにしてるので、リダイレクト先を'/index/'とする。

LOGIN_REDIRECT_URL = '/index/' 

これで完了。
http://127.0.0.1:8000/account/login/のページからログインすると、
下記の画面にリダイレクトされる。

これで、ログイン後のページ遷移の実装は完了。

この記事が気に入ったらサポートをしてみませんか?