- django-allauthでビューロジックのカスタマイズがしたい!
このような方に向けて書きました。
django-allauthの標準のビューロジックはとても良くできていますが、要件によってはカスタマイズが必要なケースもあります。
本記事ではよく使うビューロジックの調整方法を解説します。
【django-allauth】ビューロジックのカスタマイズ
成功時のリダイレクト先を設定
クラス変数のsuccess_url
にURLパターンを指定することで、リダイレクト先の指定ができます。
以下はLoginView
の例です。
from allauth.account.views import LoginView
from django.urls import reverse_lazy
class CustomLoginView(LoginView):
def get_success_url(self):
# サインアップ成功後のリダイレクト先
return reverse_lazy("home")
以下のビューについても、同じ方法でリダイレクト先の変更ができます。
- SignupView
- LoginView
- PasswordChangeView
- PasswordSetView
- PasswordResetView
- PasswordResetDoneView
- PasswordResetFromKeyView
- PasswordResetFromKeyDoneView
- EmailView
- ConfirmEmailView
- EmailVerificationSentView
ログアウトビューの場合の変数名は next_page なので注意が必要です。
class CustomLogoutView(LogoutView):
next_page = reverse_lazy("accounts:account_login")
def post(self, request, *args, **kwargs):
next_page = reverse_lazy("accounts:account_login")
ちなみに、このクラス変数を指定する方法は「リダイレクト先が固定されてしまう」というデメリットがあります。
そこで条件に応じてリダイレクトをしたい場合には、get_success_url()
メソッドをオーバーライドします。
次のコードは「スーパーユーザー権限の有無」でリダイレクト先を変更した例です。
from allauth.account.views import LoginView
from django.urls import reverse_lazy
class CustomLoginView(LoginView):
def get_success_url(self):
if self.request.user.is_superuser:
# 管理者用ダッシュボードへのリダイレクト
return reverse_lazy("admin_dashboard")
else:
# 一般ユーザー用ダッシュボードへのリダイレクト
return reverse_lazy("user_dashboard")
このように、リダイレクト先の細かい調整が必要な場合にはオーバーライドで対応しましょう。
サインアップ後に自動的にログインさせる
デフォルトではサインアップ後にメールアドレス確認メールが送信されます。
基本的には「セキュリティ確保」や「誤入力の防止」のために、デフォルトの設定を採用すべき。
ところが、ユーザー登録後にログイン状態にしたい場合もあります。
実装にあたってはform_valid()
メソッドにlogin()
メソッドを追加して対応します。
from allauth.account.views import SignupView
from django.contrib.auth import login
from django.shortcuts import redirect
class CustomSignupView(SignupView):
def form_valid(self, form):
# ユーザーを保存し、登録
response = super().form_valid(form)
# ユーザーを自動的にログインさせる
login(self.request, self.user)
# リダイレクト
return response
また、自動ログインさせる場合にはメール確認もスキップする必要があります。
settings.pyに次のコードを追加しましょう。
# メールの確認を無効化
ACCOUNT_EMAIL_VERIFICATION = "none"
# リダイレクト先を指定する場合
ACCOUNT_SIGNUP_REDIRECT_URL = "/profile/"
ログアウト時の処理を追加したい
ログアウト時の処理はLogoutView
のdispatch()
メソッドをオーバーライドします。
次のコードは、ユーザーのログアウト時間を記録したものです。
from allauth.account.views import LogoutView
from django.utils import timezone
class CustomLogoutView(LogoutView):
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated:
# ユーザーのプロファイルモデルに最終ログアウト時間を記録
request.user.profile.last_logout = timezone.now()
request.user.profile.save()
return super().dispatch(request, *args, **kwargs)
ユーザーの行動のトラッキングや不正アクセスの検知などを行う目的で実装しました。
なお、上記のコードはOneToOneField
でユーザーモデルと関連づけられたProfile
モデルがあることが前提になります。
他人が投稿したものを表示させない
日記サイトなどで本人が作成した投稿だけを表示させたい場合を解説します。
実装にはUserPassesTestMixin
という、ユーザーの判定をするミックスインを使います。
結論となるコードは以下のとおりです。
from django.core.exceptions import PermissionDenied
from django.shortcuts import redirect
class DiaryDetailView(LoginRequiredMixin, UserPassesTestMixin, DetailView):
model = DiaryEntry
template_name = "diary/entry_detail.html"
context_object_name = "entry"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["page_title"] = self.object.title
return context
def test_func(self):
"""権限がある人を定義"""
entry = self.get_object()
return self.request.user == entry.author
def handle_no_permission(self):
"""権限がない場合の処理"""
return redirect("diary:home")
まず、ミックスインの記載順から注意が必要です。
- ログインしていない人を排除
- 権限がない人への処理を定義
- ビューを表示する
といった形で順番が非常に重要になってきますので、コード例のような順序で継承する必要があります。
また、test_func()
メソッドには「どんな人に権限があるか」を定義します。
def test_func(self):
entry = self.get_object()
return self.request.user == entry.author
self.get_object() は DetailView 固有のメソッドです。
handle_no_permission()
メソッドには「権限がない場合の処理」を記載します。
ここでは日記サイトのホーム画面にリダイレクトするようにしました。
def handle_no_permission(self):
"""権限がない場合の処理"""
return redirect("diary:home")
リダイレクト以外にも、次のような処理が考えられます。
処理内容 | コード |
---|---|
403エラー | raise PermissionDenied() |
JSONレスポンス | return JsonResponse( {“error”: “message”}, status=403, ) |
カスタムエラーページ | return render( self.request, “403.html”, status=403, ) |
コメント