Search code examples
djangodjango-authentication

Django can login but can't logout - 405 Method Not Allowed


When I try to login using http://127.0.0.1:8000/accounts/login/ it works fine and redirected and creates a sessionid, but when I try to logout using http://127.0.0.1:8000/accounts/logout/ it shows http error 405 and not deleting the sessionid

Request URL: http://127.0.0.1:8000/accounts/logout/ Request Method: GET Status Code: 405 Method Not Allowed

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 %}

Solution

  • In Django, logging out requires a POST request for security reasons, to prevent CSRF attacks. If you try to log out using a direct URL, which sends a GET request, Django will reject it and show a "405 Method Not Allowed" error.

    To fix it, create a logout form that sends a POST request. This can be a simple form with just a logout button. Place this form where you want the logout functionality in your templates, like in a header or sidebar. If you want you can create a separate html file and include the template where necessary.

    Sample logout form can be like this:

    <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>
    

    If you want to redirect the user to a specific page after logging out, set LOGOUT_REDIRECT_URL in your settings.py file like:

    LOGOUT_REDIRECT_URL = '/home' #anywhere you like
    

    You can find more information about it in django docs