🐍
【Python】django-allauthを用いて、ユーザーログイン機能を実装
達成目標
django-allauth
を用いて、ユーザーログイン機能を実装できる。
ログイン画面
新規登録画面
ログイン後遷移画面
前提
- アプリケーションのトップページが表示されている状態かつデータベースの設定が完了している状態から解説をしていく。
開発環境の構築がまだの方はこちらから↓
1.requirements.txt ファイルの準備と編集
ファイルの作成
ターミナルで実行(作成済みの場合は飛ばす)
New-Item requirements.txt
ファイルの編集
requirements.txt
django==4.2
django-allauth==0.53.0 # 追加
モジュールをインストールコマンドを実行
docker-compose exec web pip install -r requirements.txt
出力結果
Downloading django-allauth-0.53.0.tar.gz (735 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 735.8/735.8 kB 2.7 MB/s eta 0:00:00
Preparing metadata (setup.py) ... done
Collecting python3-openid>=3.0.8 (from django-allauth==0.53.0->-r requirements.txt (line 33))
インストールされたかを確認
パッケージ一覧の確認コマンド
docker-compose exec web pip list
インストール済みのパッケージをrepuirement.txtに記録するコマンド
docker-compose exec web pip freeze > requirements.txt
settings.py
ファイルの編集
2.
settings.py
のINSTALLED_APPS
に追加
settings.pyファイルの編集①
INSTALLED_APPS = [
# 既存のアプリ
'django.contrib.sites', # 必須
'allauth',
'allauth.account',
'allauth.socialaccount', # SNSログインを使用する場合
'allauth.socialaccount.providers.google', # 必要なSNSプロバイダを追加
]
SITE_ID = 1 # 必須
settings.py
のINSTALLED_APPS
に追加
settings.pyファイルの編集②
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend', # Djangoのデフォルト認証
'allauth.account.auth_backends.AuthenticationBackend', # allauthの認証
]
settings.py
のその他設定を追加
settings.pyファイルの編集③
# ログイン後のリダイレクト先
LOGIN_URL = '/accounts/login/'
ACCOUNT_LOGOUT_REDIRECT_URL = '/'
# サインアップ時のメール確認機能を無効化(デフォルトはTrue)
ACCOUNT_EMAIL_VERIFICATION = "none"
# ユーザー名の使用を制御(Trueでユーザー名必須)
ACCOUNT_USERNAME_REQUIRED = True
# メールアドレスの使用設定
ACCOUNT_EMAIL_REQUIRED = True
urls.py
の編集
3.プロジェクトフォルダ内のurls.pyへ以下を追加
from django.views.generic import TemplateView
from allauth.account.views import LoginView, SignupView
class CustomLoginView(LoginView):
template_name = 'account/login.html'
class CustomSignupView(SignupView):
template_name = 'account/signup.html'
path('accounts/', include('allauth.urls')), # django-allauthのURL
path('', TemplateView.as_view(template_name='home.html'), name='home'),
path('login/', CustomLoginView.as_view(), name='account_login'),
path('signup/', CustomSignupView.as_view(), name='account_signup'),
4.テンプレートの作成
テンプレートフォルダとファイルの作成
ターミナルで実行
mkdir templates/account
New-Item templates/home.html
New-Item templates/account/login.html
New-Item templates/account/signup.html
テンプレートファイルの編集
home.htmlの中身
home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
background-color: #f8f9fa;
font-family: 'Arial', sans-serif;
}
.container {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.card {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 10px;
width: 100%;
max-width: 30rem;
}
.btn-custom {
background-color: #007bff;
color: white;
font-size: 16px;
padding: 12px 24px;
border-radius: 30px;
border: none;
transition: background-color 0.3s;
}
.btn-custom:hover {
background-color: #0056b3;
}
.btn-custom:focus {
outline: none;
}
h1 {
font-size: 2.5rem;
color: #333;
text-align: center;
margin-bottom: 30px;
}
.card-body {
text-align: center;
padding: 2rem;
}
.d-grid {
gap: 15px;
}
.btn-danger {
width: 100%;
}
</style>
</head>
<body>
<div class="container">
<div class="card">
<div class="card-body">
<h1>Welcome to Our Site</h1>
<p class="lead">Please log in or sign up to continue</p>
<div class="d-grid gap-3">
{% if user.is_authenticated %}
<p>ログインしています: {{ user.username }}</p>
<form action="{% url 'account_logout' %}" method="post">
{% csrf_token %}
<button type="submit" class="btn btn-danger">Logout</button>
</form>
{% else %}
<p>ログインしていません</p>
<a href="{% url 'account_login' %}" class="btn btn-primary">Login</a>
<a href="{% url 'account_signup' %}" class="btn btn-success">Sign Up</a>
{% endif %}
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
login.htmlの中身
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Site</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
background-color: #f7f7f7;
font-family: 'Arial', sans-serif;
}
.card {
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 28rem;
}
.card-body {
padding: 2rem;
}
.form-label {
font-weight: bold;
margin-bottom: 0.5rem;
}
.form-control {
border-radius: 0.375rem;
padding: 0.75rem 1.25rem;
border: 1px solid #ccc;
}
.btn-custom {
background-color: #007bff;
color: #fff;
border: none;
border-radius: 0.375rem;
padding: 0.75rem 1.25rem;
font-size: 1rem;
transition: background-color 0.3s;
}
.btn-custom:hover {
background-color: #0056b3;
}
.text-muted {
color: #6c757d;
}
.form-control:focus {
border-color: #007bff;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
.card-title {
color: #343a40;
margin-bottom: 1.5rem;
}
.text-primary {
text-decoration: none;
}
.text-primary:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<header>
<!-- ナビゲーションバーなど -->
</header>
<main class="container py-4">
<div class="d-flex justify-content-center align-items-center vh-100">
<div class="card shadow-sm">
<div class="card-body">
<h2 class="card-title text-center mb-4">Create an Account</h2>
<form method="post" class="mt-4">
{% csrf_token %}
{{ form.non_field_errors }}
{% for field in form %}
<div class="mb-3">
<label for="{{ field.id_for_label }}" class="form-label">{{ field.label }}</label>
{{ field }}
{% if field.errors %}
<div class="text-danger small">{{ field.errors|striptags }}</div>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-custom w-100">Sign Up</button>
</form>
<p class="text-center mt-3">
Already have an account? <a href="{% url 'account_signup' %}" class="text-primary">Sign In</a>
</p>
</div>
</div>
</div>
</main>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
signup.htmlの中身
signup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sign In</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
background-color: #f7f7f7;
font-family: 'Arial', sans-serif;
}
.card {
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 28rem;
}
.card-body {
padding: 2rem;
}
.form-label {
font-weight: bold;
margin-bottom: 0.5rem;
}
.form-control {
border-radius: 0.375rem;
padding: 0.75rem 1.25rem;
border: 1px solid #ccc;
}
.btn-custom {
background-color: #007bff;
color: #fff;
border: none;
border-radius: 0.375rem;
padding: 0.75rem 1.25rem;
font-size: 1rem;
transition: background-color 0.3s;
}
.btn-custom:hover {
background-color: #0056b3;
}
.text-muted {
color: #6c757d;
}
.form-control:focus {
border-color: #007bff;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
.card-title {
color: #343a40;
margin-bottom: 1.5rem;
}
.text-primary {
text-decoration: none;
}
.text-primary:hover {
text-decoration: underline;
}
.form-group {
margin-bottom: 1rem;
}
</style>
</head>
<body>
<div class="container py-4">
<div class="d-flex justify-content-center align-items-center vh-100">
<div class="card shadow-sm">
<div class="card-body">
<h2 class="card-title text-center mb-4">Sign In</h2>
<form method="post" class="mt-4">
{% csrf_token %}
{{ form.non_field_errors }}
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}" class="form-label">{{ field.label }}</label>
{{ field }}
{% if field.errors %}
<div class="text-danger small">{{ field.errors|striptags }}</div>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-custom w-100">Sign In</button>
</form>
<p class="text-center mt-3">
Don't have an account? <a href="{% url 'account_login' %}" class="text-primary">Login</a>
</p>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
5.管理者ユーザーを作成
requirements.txtの内容が表示される。
docker-compose exec web python manage.py createsuperuser
出力結果
$ docker-compose exec web python manage.py createsuperuser
Username (leave blank to use 'root'): admin
Email address: admin@example.com
Password:
Password (again):
Superuser created successfully.
6.画面遷移確認
http://localhost:8000/login/
にアクセスし、管理者でログイン
ログイン画面
http://localhost:8000/
へ遷移するかを確認
ログイン後遷移画面
Lgout
ボタンを押して、http://localhost:8000/
へ遷移するかを確認
ログインアウト後画面
Sign up
ボタンを押して、http://localhost:8000/signup/
に遷移するか確認
新規登録画面
http://localhost:8000/
へ遷移するかを確認
新規ユーザー登録を行ったあと、
新規登録後画面
おまけ
ユーザー一覧を確認する方法
docker-compose exec web python manage.py shell -c "from django.contrib.auth.models import User; import json; print(json.dumps([{'username': u.username, 'email': u.email} for u in User.objects.all()], indent=4))"
出力結果
JSON形式で返してくれる
[
{
"username": "admin",
"email": "admin@example.com"
},
{
"username": "test1",
"email": "test@test.com"
}
]
Discussion