今回は、クラスベースビューにおけるログイン、ログアウト処理や、
リダイレクト処理、セッション時間の変更などみていきます。
前提
・「my_app」というアプリを作成、「settings.py」に登録
・「manage.py」と同じ階層に「templates」「static」ディレクトリを作成し、読込先のディレクトリのパスをこちらに変更
.
.
.
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATE_DIR = os.path.join(BASE_DIR, 'templates')
STATIC_DIR = os.path.join(BASE_DIR, 'static').
.
.
.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATE_DIR,],
.
.
.
STATIC_URL = '/static/'
STATICFILES_DIRS = (
STATIC_DIR,
)
・プロジェクトディレクトリの「urls.py」に以下のようにパスを登録
path('my_app/', include('my_app.urls')),
ユーザー登録、ログイン、ログアウト
モデルの作成
from django.db import models
from django.urls import reverse_lazy
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser, PermissionsMixin
)
# Create your models here.
class UserManager(BaseUserManager):
def create_user(self, username, email, password=None):
if not email:
raise ValueError('メールアドレスを入力してください')
user = self.model(
username=username,
email=email
)
user.set_password(password)
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=150)
email = models.EmailField(max_length=255, unique=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
def get_absolute_url(self):
return reverse_lazy('my_app:home')
「settings.py」の修正
.
.
.
AUTH_USER_MODEL = 'my_app.User'
マイグレーションの実行
python manage.py makemigrations my_app
python manage.py migrate
「forms.py」の作成
from django import forms
from django.db import models
from django.forms import fields
from .models import User
from django.contrib.auth.password_validation import validate_password
class RegistForm(forms.ModelForm):
username = forms.CharField(label='名前')
age = forms.IntegerField(label='年齢', min_value=0)
email = forms.EmailField(label='メールアドレス')
password = forms.CharField(label='パスワード', widget=forms.PasswordInput())
class Meta:
model = User
fields = ['username', 'age', 'email', 'password']
def save(self, commit=False):
user = super().save(commit=False)
validate_password(self.cleaned_data['password'], user)
user.set_password(self.cleaned_data['password'])
user.save()
return user
class UserLoginForm(forms.Form):
email = forms.EmailField(label='メールアドレス')
password = forms.CharField(label='パスワード', widget=forms.PasswordInput())
from django import forms
from django.db import models
from django.forms import fields
from .models import User
from django.contrib.auth.password_validation import validate_password
class RegistForm(forms.ModelForm):
username = forms.CharField(label='名前')
age = forms.IntegerField(label='年齢', min_value=0)
email = forms.EmailField(label='メールアドレス')
password = forms.CharField(label='パスワード', widget=forms.PasswordInput())
class Meta:
model = User
fields = ['username', 'age', 'email', 'password']
def save(self, commit=False):
user = super().save(commit=False)
validate_password(self.cleaned_data['password'], user)
user.set_password(self.cleaned_data['password'])
user.save()
return user
class UserLoginForm(forms.Form):
email = forms.EmailField(label='メールアドレス')
password = forms.CharField(label='パスワード', widget=forms.PasswordInput())
「views.py」の修正
from django.shortcuts import redirect, render
from django.views.generic.edit import CreateView, FormView
from django.views.generic.base import TemplateView, View
from .forms import RegistForm
from .forms import UserLoginForm
from django.contrib.auth import authenticate, login, logout
# Create your views here.
class HomeView(TemplateView):
template_name = 'home.html'
class RegistUserView(CreateView):
template_name = 'regist.html'
form_class = RegistForm
class UserLoginView(FormView):
template_name = 'user_login.html'
form_class = UserLoginForm
def post(self, request, *args, **kwargs):
email = request.POST['email']
password = request.POST['password']
user = authenticate(email=email, password=password)
if user is not None and user.is_active:
login(request, user)
return redirect('my_app:home')
class UserLogoutView(View):
def get(self, request, *args, **kwargs):
logout(request)
return redirect('my_app:user_login')
「urls.py」の修正
from django.urls import path
from .views import (
RegistUserView, HomeView, UserLoginView, UserLogoutView
)
app_name = 'my_app'
urlpatterns = [
path('home', HomeView.as_view(), name='home'),
path('regist', RegistUserView.as_view(), name='regist'),
path('user_login', UserLoginView.as_view(), name='user_login'),
path('user_logout', UserLogoutView.as_view(), name='user_logout'),
]
HTMLファイルの作成
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand navbar-light bg-light">
<a href="{% url 'my_app:home' %}" class="navbar-brand">ホーム</a>
{% if user.is_authenticated %}
<a href="{% url 'my_app:user_logout' %}" class="navbar-brand">ログアウト</a>
{% else %}
<a href="{% url 'my_app:user_login' %}" class="navbar-brand">ログイン</a>
<a href="{% url 'my_app:regist' %}" class="navbar-brand">ユーザー登録</a>
{% endif %}
</nav>
<div class="container py-4">
{% block content %}{% endblock %}
</div>
</body>
</html>
{% extends 'base.html' %}
{% block content %}
<h1>ホーム画面</h1>
{% endblock %}
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="ユーザー登録">
</form>
{% endblock %}
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="ログイン">
</form>
{% endblock %}
未ログイン時に別ページへリダイレクト
未ログイン状態で、ログインしていないと見れないページにアクセスしたときに、
別ページへリダイレクトする方法をみていきます。
「views.py」の修正
.
.
.
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
.
.
.
@method_decorator(login_required, name='dispatch')
class UserView(TemplateView):
template_name = 'user.html'
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
パスの追加
from django.urls import path
from .views import (
RegistUserView, HomeView, UserLoginView, UserLogoutView, UserView
)
app_name = 'my_app'
urlpatterns = [
path('home', HomeView.as_view(), name='home'),
path('regist', RegistUserView.as_view(), name='regist'),
path('user_login', UserLoginView.as_view(), name='user_login'),
path('user_logout', UserLogoutView.as_view(), name='user_logout'),
path('user', UserView.as_view(), name='user'),
]
「base.html」の修正
<nav class="navbar navbar-expand navbar-light bg-light">
.
.
.
{% endif %}
<a href="{% url 'my_app:user' %}" class="navbar-brand">ユーザー画面</a>
</nav>
「settings.py」の修正(未ログイン時の遷移先を指定)
.
.
.
LOGIN_URL = '/my_app/user_login'
未ログイン状態

ログイン状態

また、この時点では未ログイン状態で「ユーザー画面」を押してログインすると、ホーム画面に遷移してしまいます。

これを、「ユーザー画面」→「ログイン」→「ユーザー画面」となるよう修正します。

「user_login.html」の修正
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="hidden" name="next" value="{{ request.GET.next }}">
<input type="submit" value="ログイン">
</form>
{% endblock %}
「views.py」の修正
.
.
.
class UserLoginView(FormView):
template_name = 'user_login.html'
form_class = UserLoginForm
def post(self, request, *args, **kwargs):
email = request.POST['email']
password = request.POST['password']
user = authenticate(email=email, password=password)
next_url = request.POST['next']
if user is not None and user.is_active:
login(request, user)
if next_url:
return redirect(next_url)
return redirect('my_app:home')
.
.
.
LoginView, LogoutView
「forms.py」の修正
.
.
.
from django.contrib.auth.forms import AuthenticationForm
.
.
.
# class UserLoginForm(forms.Form):
# email = forms.EmailField(label='メールアドレス')
# password = forms.CharField(label='パスワード', widget=forms.PasswordInput())
class UserLoginForm(AuthenticationForm):
username = forms.EmailField(label='メールアドレス') # ユーザーを一意に指定するもの
password = forms.CharField(label='パスワード', widget=forms.PasswordInput())
「views.py」の修正
.
.
.
# class UserLoginView(FormView):
# template_name = 'user_login.html'
# form_class = UserLoginForm
# def post(self, request, *args, **kwargs):
# email = request.POST['email']
# password = request.POST['password']
# user = authenticate(email=email, password=password)
# next_url = request.POST['next']
# if user is not None and user.is_active:
# login(request, user)
# if next_url:
# return redirect(next_url)
# return redirect('my_app:home')
class UserLoginView(LoginView):
template_name = 'user_login.html'
authentication_form = UserLoginForm
# class UserLogoutView(View):
# def get(self, request, *args, **kwargs):
# logout(request)
# return redirect('my_app:user_login')
class UserLogoutView(LogoutView):
pass # これのみ
.
.
.
「settings.py」の修正
.
.
.
LOGIN_REDIRECT_URL = '/my_app/home' #ログイン時のリダイレクト先
LOGOUT_REDIRECT_URL = '/my_app/user_login' #ログアウト時のリダイレクト先

セッション
デフォルトのセッション時間を変更
.
.
.
SESSION_COOKIE_AGE = 1 # 1秒
ログインしてから1秒以上経つと、自動的にログアウトされます。

「forms.py」の修正
.
.
.
class UserLoginForm(AuthenticationForm):
username = forms.EmailField(label='メールアドレス') # ユーザーを一意に指定するもの
password = forms.CharField(label='パスワード', widget=forms.PasswordInput())
remember = forms.BooleanField(label='ログイン状態を保持', required=False)
「views.py」の修正
.
.
.
class UserLoginView(LoginView):
template_name = 'user_login.html'
authentication_form = UserLoginForm
def form_valid(self, form):
remember = form.cleaned_data['remember']
if remember:
self.request.session.set_expiry(100000000)
return super().form_valid(form)
.
.
.

今回は以上になります。
ご覧いただきありがとうございました!
続きはこちら↓
コメント