Fork me on GitHub

Often people try to determine if the HTTP request is a POST request by checking request.POST. The view thus looks like:

def my_view(request):
    if request.POST:
        # …
    # …

Why is it a problem?

Because POST requests do not per se carry data. By checking if request.POST, we are checking the truthiness of the request.POST. This is a QueryDict [Django-doc]. A QueryDict has as truthiness False, if the QueryDict is empty. But not all POST requests have “payload”. For example it is possible that a confirm box to confirm deleting an object makes a POST request, but without any data as payload. In that case the if request.POST check will fail, but request.method will still be 'POST'.

What can be done to resolve the problem?

One should check the request method with:

def my_view(request):
    if request.method == 'POST':
        # …
    # …

In a class-based view, the “routing” is handled by the view, and thus it will, based on the request method trigger the .get(…), .post(…), etc. methods.

Extra tips

One can also limit the methods that have access to a certain view with the @require_http_methods(…) decorator [Django-doc] or related decorators. It is often better not only to check what method is used, but also block requests with a request method that is not foreseen.