LoginSignup
9
17

More than 3 years have passed since last update.

Django allauthにおけるログイン画面の作成

Posted at

Django-allauth

Django-allauthは、簡単にアカウント作成やログイン機能をDjangoで実装できるパッケージです。

本記事では、django-allauthのテンプレートを見栄えの良い表示にし、テストの実行まで記載しています。
プロジェクトの始め方は、Djangoのプロジェクトを始めるを参考にしてください。

allauthのテンプレート

base.pyに設定した、templates/allauthの下に、pythonの仮想環境に関するパッケージがあるvenv/libから
venv/lib/python3.6/site-packages/allauth/account/templatesの中身をtemplates/allauthにコピーします。

base.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(BASE_DIR, 'templates', 'allauth'), #ログインテンプレート等などを置く場所
            os.path.join(BASE_DIR, 'templates'), #テンプレートを置く場所
        ],

django-allauthのurlに関して

django-allauthで定義されている認証に関するurlは、venv/lib/python3.6/site-packages/allauth/account/urls.py
に記載されている。

*/allauth/account/urls.py
urlpatterns = [
    url(r"^signup/$", views.signup, name="account_signup"),
    url(r"^login/$", views.login, name="account_login"),
    url(r"^logout/$", views.logout, name="account_logout"),
    ...
]

もし、ヘッダー(HTML)でログアウトへのリンクを書く場合は、上記のurlpatternsに設定してある、nameを以下のように記載すれば良い。

<a class="dropdown-item" href="{% url 'account_logout' %}">ログアウト</a>

画面のデザイン

django-allauthの画面のhtmlを変更するとき、困ったことが、以下のように、テンプレート構文である{% for field in form %}のループでfieldが設定されるため、cssの設定方法が分かりづらいことでした。

login.html
{% for field in form%}
      <div class="account-form">
        <div class="account-filed">
            {% if forloop.last %}
            <span class="last-field">{{ field }}</span>
              <span class="login-maintain">ログイン状態を維持する</span>
            {% else %}
              <span class="non-last-field">{{ field }}</span>
            {% endif %}
        </div>

        <div class="account-helptext">
          {% if field.errors %}
            <p>{{ field.errors.0 }}</p>
          {% endif %}
        </div>
      </div>
    {% endfor%}

対処法としては、まず、初期状態で描画し、Googleの検証でどのような要素が含まれているか確認してみます。
そして、filedをspanやdivで囲み、その要素や新たな要素の変更・追加を行う必要があります。

例えば、上記のlogin.htmlにはinputが見て取れませんが、inputを含んだものになっています。
そのため、以下のように設定をすると、見た目が反映されます。

input {
    border:none;
    font-size: 60%;
    padding-top:25px;
    padding-bottom: 0px;
    border-bottom: 1px solid #ff7700;
    outline: none;
    font: 800;

}

ログイン画面の例は以下の通りです。

git : login.html
git : account-style.css

スクリーンショット 2019-08-17 16.11.03.png

同様に、アカウント作成やパスワード変更の例もgitにあげています。

テスト

ここでは、アカウント作成、ログイン、ログアウト機能のテストを実装します。
まず、mainアプリにテストを行うフォルダを作成します。


mkdir ./main/tests
touch ./main/test/__init__.py
rm ./main/tests.py 

test_allauth.pyにアカウント作成とログインに関するテストを書いた。
Djangoによるテストでは、test_*.pyというファイル形式とし、 ./manage.py test でテストを実行できる。

test_allauth.py
from django.test import TestCase
from django.core import mail
from allauth.account.forms import LoginForm, SignupForm
from allauth.utils import get_user_model
from django.contrib import auth
from django.urls import reverse
from unittest.mock import patch
from main import models

class TestSignUp(TestCase):
    def setUp(self):
        self.post_user_data = {
            "username": "username543",
            "email": "user@domain.com",
            "password1": "abcabcabc",
            "password2": "abcabcabc",
        }

    def test_user_signup_page_loads_correctly(self):
        response = self.client.get(reverse('account_signup'))
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'account/signup.html')
        self.assertContains(response, 'SIGN UP')
        self.assertIsInstance(
            response.context['form'], SignupForm
        )

    def test_user_signup_page_submission_works(self):
        post_data = self.post_user_data 
        response = self.client.post(
            reverse("account_signup"), post_data
        )

        #homeへリダイレクト
        self.assertEqual(response.status_code, 302)

        #ユーザが追加されたか確認
        self.assertTrue(
            models.User.objects.filter(
                email=self.post_user_data['email']
            ).exists()
        )
        #ログイン状態か
        self.assertTrue(
            auth.get_user(self.client).is_authenticated
        )

    def test_user_login_page_loads_correctly(self):
        response = self.client.get(reverse('account_login'))
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'account/login.html')
        self.assertContains(response, 'LOGIN')
        self.assertIsInstance(
            response.context['form'], LoginForm
        )

    def test_user_login_page_submission_works(self):
        user1 = models.User.objects.create_user(
            self.post_user_data['username'],
            self.post_user_data['email'],
            self.post_user_data['password1']
        )
        user1.save()

        post_data = {
            'login':self.post_user_data['email'],
            'password':self.post_user_data['password1']    
        }

        #ユーザが追加されたか確認
        self.assertTrue(
            models.User.objects.filter(
                email=self.post_user_data['email']
            ).exists()
        )

        response = self.client.post(
            reverse("account_login"), post_data
        )

        #ログイン状態か
        self.assertTrue(
            auth.get_user(self.client).is_authenticated
        )

        #homeへリダイレクト
        self.assertEqual(response.status_code, 302)

9
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
17