Django может войти в систему, но не может выйти из нее - 405 Method Not Allowed
Когда я пытаюсь войти в систему, используя http://127.0.0.1:8000/accounts/login/, он работает нормально, перенаправляет и создает sessionid, но когда я пытаюсь выйти из системы, используя http://127.0.0.1:8000/accounts/logout/, он показывает http ошибку 405 и не удаляет sessionid
URL запроса: http://127.0.0.1:8000/accounts/logout/. Метод запроса: GET Код состояния: 405 Метод не разрешен
settings.py
INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'app.apps.AppConfig',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
STATIC_URL = 'static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'upload'
LOGIN_REDIRECT_URL = '/'
urls.py
urlpatterns = [
path('',include('app.urls')),
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
login.html
<form method="POST" action="{% url 'login' %}" class="form">
{% csrf_token %}
<center>
<div class="logo f-logo">
<i class="fa-brands fa-blogger"></i>
</div>
<div class="inputs">
<div>
<div class="search-bar s-active input">
{{form.username}}
<div class="animated-search">
<i class="uil uil-envelope-alt"></i>
</div>
</div>
<div class="search-bar s-active input">
{{form.password}}
<div class="animated-search">
<i class="uil uil-key-skeleton"></i>
</div>
</div>
</div>
<button class="btn btn-primary rounded" type="submit">Login<span class="material-icons">arrow_right_alt</span></button>
<p>Not have an account?<a href="signup.html">Sign up</a></p>
</div>
</center>
</form>
logged_out.html
{% extends 'base.html' %}
{% block title %} Blog | Logout {% endblock title %}
{% block content %}
<div class="container">
<center>
<div class="typo">
<p>You have been successfully logged out.
<a href="{% url 'login' %}">Login again</a>
</p>
</div>
</center>
</div>
{% endblock content %}
Как отметил Дмитрий, необходимо использовать метод POST
, начиная с версии Django 4.1
Вот простой пример:
<form method="post" action="{% url 'logout' %}">
{% csrf_token %}
<button type="submit">Log Out</button>
</form>
Где logout
URL указывает на LogoutView
или аналогичный класс или функцию представления.
В Django выход из системы требует POST-запроса по соображениям безопасности, чтобы предотвратить CSRF attacks
. Если вы попытаетесь выйти из системы, используя прямой URL, который отправляет GET-запрос, Django отклонит его и выдаст ошибку "405 Method Not Allowed".
Чтобы решить эту проблему, создайте форму выхода из системы, которая отправляет запрос POST
. Это может быть простая форма с кнопкой выхода из системы. Разместите эту форму там, где вы хотите видеть функцию выхода из системы в ваших шаблонах, например в заголовке или боковой панели. При желании вы можете создать отдельный html-файл и включить шаблон туда, где это необходимо.
Образец формы выхода из системы может выглядеть следующим образом:
<form action="{% url 'logout' %}" method="post">
{% csrf_token %} #csrf_token is very important to have as this is POST request
<button type="submit">Logout</button>
</form>
Если вы хотите перенаправить пользователя на определенную страницу после выхода из системы, задайте LOGOUT_REDIRECT_URL
в вашем settings.py
файле следующее:
LOGOUT_REDIRECT_URL = '/home' #anywhere you like
Вы можете найти больше информации об этом в django docs
Вот фундаментальная ошибка, вызывающая эту ошибку, как это случилось со мной:
НЕ ИСПОЛЬЗУЙТЕ ЭТО:
<a href="{% url 'logout' %}">Log out</a>
ИСПОЛЬЗУЙТЕ ЭТО:
<form method="post" action="{% url 'logout' %}">
{% csrf_token %}
<button type="submit">logout</button>
</form>
Я использовал для входа в систему атрибут href, который по умолчанию формирует GET-запрос к серверу для запроса страницы входа в систему. Это, конечно, сработало, потому что на странице входа есть своя форма для ввода имени пользователя и пароля и кнопка отправки.
Я попытался использовать такой же тип ссылки для выхода из системы (показано выше), но это привело к 405 ошибке, потому что выход из системы не вызывает новую страницу. Она автоматически пытается вывести пользователя из системы. В ЭТОМ И ЗАКЛЮЧАЕТСЯ ПРИНЦИПИАЛЬНАЯ РАЗНИЦА. Поскольку для выхода пользователя из системы требуется POST-запрос, решением было заменить тег кнопкой, вложенной внутрь тегов формы, как предлагалось ранее. Это позволило мне указать метод запроса как POST.
Вы можете задаться вопросом, почему для выхода пользователя из системы необходим POST-запрос? Ну, потому что выход пользователя из системы, скорее всего, требует передачи на сервер конфиденциальной информации о выходящем пользователе, и эта информация должна быть защищена.