Search code examples
pythonpython-3.xdjangodjango-formsdjango-authentication

Django built in Logout view `Method Not Allowed (GET): /users/logout/`


Method Not Allowed (GET): /users/logout/
Method Not Allowed: /users/logout/
[10/Dec/2023 12:46:21] "GET /users/logout/ HTTP/1.1" 405 0

This is happening when I went to url http://127.0.0.1:8000/users/logout/

urls.py:

from django.contrib.auth import views as auth_views

urlpatterns = [
    ...other urls...
    path('users/logout/', auth_views.LogoutView.as_view(), name='logout'),
]

I am expecting user to logout


Solution

  • Since , you need to do this through a POST request, since it has side-effects. The fact that it worked with a GET request was (likely) a violation of the HTTP protocol: it made it possible for certain scripts to log out users, without the user wanting to. So a POST request also protects against cross-site request forgery (CSRF) [wiki].

    So in the template, work with a mini-form:

    <form method="post" action="{% url 'logout' %}">
        {% csrf_token %}
        <button type="submit">logout</button>
    </form>
    

    Also note that Django's LogoutView [Django-doc] does not render a page: it only works with a POST request that logs out the user that is making the request, and redirect to the page provided by the ?next_page=… parameter, or if such parameter is absent with LOGOUT_REDIRECT_URL [Django-doc]. Visiting the page will thus not work and return a 405 Method Not Allowed.

    If you thus want to make a page to logout, you add an extra view:

    from django.views.generic import TemplateView
    
    urlpatterns = [
        # …,
        path(
            'do-logout/',
            TemplateView.as_view(template_name='my_template.html'),
            name='do-logout',
        )
    ]

    where the my_template.html then thus contains such miniform. You can thus visit /do-logout/ (or use another path) to render a page with a miniform to log out.