🐍
【Django】ログアウトページ遷移時に405エラーが発生した話
概要・目的
- Djangoの基礎的な教材に倣いながら、作成したWebサイトに「ログイン・ログアウト機能」を実装したが、いざログアウトを行おうとすると「405エラー」が発生してしまいました...
- 原因を探索したところ、DjangoにてWebサイトを実装する場合は今後も念頭に置かねばならないものであったため、こちらに備忘録として記載します。
事象の内容と当時の状況
事象
- ログインしている状態で表示されている「ログアウト」ボタンをクリックすると、「405 エラー」が表示されました。
記述したコード(template)
template
{% extends "base.html" %}
{% load django_bootstrap5 %}
{% block content %}
{% if user.is_authenticated %}
<p>
{{ user }}でログインしています
</p>
<p>
<a href="{% url 'logout' %}">
{% csrf_token %}
{% bootstrap_button button_type="submit" button_class="btn-danger" content="ログアウト" size="md" %}
</a>
</p>
{% else %}
{% endblock %}
原因と解決方法
原因
- コードにあるように、画面遷移に
<a>
タグを用いており、<a>
タグによるリクエストはGET
となります。 - 一方で、Djangoのデフォルトではログアウトビューは
POST
メソッドのみを受け付ける仕様になっており、このリクエスト方式の差により「405 エラー」が発生したようです。
解決方法
- 「ログアウト」ボタンクリック時に実行されるリクエスト方式が
POST
となるよう、<a>
タグから<form>
タグに修正します。 - また、
<form>
タグ内でのmethod
属性をPOST
に指定します。
template
{% extends "base.html" %}
{% load django_bootstrap5 %}
{% block content %}
{% if user.is_authenticated %}
<p>
{{ user }}でログインしています
</p>
<p>
<form action="{% url 'logout' %}" method="post">
{% csrf_token %}
{% bootstrap_button button_type="submit" button_class="btn-danger" content="ログアウト" size="md" %}
</form>
</p>
{% else %}
{% endblock %}
備考
- Djangoにおけるログアウトビューが
POST
のみを受け付けている理由は、GET
よりもセキュリティ上安全であるためです。GET
ではURLのクエリパラーメータとして情報が露出してしまいますが、POST
では露出しません。 - 上記の理由から、ログアウトビューを呼び出す際のリクエスト方法は
POST
固定でよいかと思います。
Discussion