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

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.