Why Django Uses POST for Logout (And What's a CSRF Token?)

A GET request is triggered simply by visiting a URL. Your browser hits the link, the server responds. Simple.

A POST request, on the other hand, requires a form submission — the user has to actively submit data through a form.

This distinction matters more than it sounds.

The Problem with GET-based Logout

Imagine your logout view is wired to a GET request at /logout. Now imagine a malicious website drops this somewhere in their HTML:

<img src="https://yoursite.com/logout">

When a logged-in user visits that page, their browser dutifully tries to load the "image" — which is actually your logout URL. No click required. No warning. The user is silently logged out without knowing why.

This is called a Cross-Site Request Forgery (CSRF) attack — a malicious site tricks the browser into making a request on the user's behalf.

Why POST Stops This

POST requests can't be triggered by a simple <img> tag or a link. They require a proper form submission. But that alone isn't enough — a malicious site could still craft a hidden form and auto-submit it with JavaScript.

That's where the CSRF token comes in.

What Is a CSRF Token?

Django automatically generates a secret, one-time token and embeds it in every form using the {% csrf_token %} template tag:

<form method="POST">
    {% csrf_token %}  <!-- Django injects a hidden secret key here -->
    ...
</form>

This renders in the browser as something like:

<input type="hidden" name="csrfmiddlewaretoken" value="abc123xyz...">

Django generates a hidden secret token: html When form is submitted Django checks: Token matches → legitimate request → process it Token missing → possible attack → reject it Every POST form in Django must have {% csrf_token %} or Django will reject the submission with a 403 error.

When the form is submitted, Django checks:

  • Does this token match what I generated for this session?
  • ✅ Yes → legitimate request, process it
  • ❌ No → reject it, possible attack

A malicious site has no way to know your token. It's unique per session and never exposed cross-origin. So even if they craft a fake form pointing at your server, the token check will fail and Django will reject it.

The Rule of Thumb

Action Method Why
Reading data GET Safe, no side effects
Changing data (login, logout, submit) POST + CSRF token Protected from forgery

Any view that changes state — logging in, logging out, saving a form — should use POST and include Django's CSRF protection. It's a small habit that closes a surprisingly common attack vector.