概要・目的
- 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固定でよいかと思います。