Exception: You cannot access body after reading from request's data stream

kev picture kev · Oct 25, 2013 · Viewed 26.5k times · Source

Since Django 1.5 raw post data is accessible via request.body.

In my application I sometimes get data send via a form and sometimes raw data (json for example). Is there any way to write a function like this that does not fail?

def get_post_var(request, name):
    result = request.POST.get(name)
    if result:
        return result

    post_body = dict(urlparse.parse_qsl(request.body))
    result = post_body.get(name)
    if result:
        return result

    return None

Answer

Adam Easterling picture Adam Easterling · Feb 21, 2015

The error You cannot access body after reading from request's data stream will be triggered on a request if (1) that request method is POST, (2) that request's POST dictionary is accessed in middleware, in either process_request or process_view and (3) within the view function, request.body is accessed. It is on (3) that the error will be raised, even though the real cause of the bug is (2).

In order to resolve the error, you need to examine your middleware for where it accesses request.POST and modify it such that it doesn't access request.POST anymore.

The Django docs say that middleware should not access request.POST, and this is one consequence of ignoring that recommendation.

Also check out this Django ticket on the issue, which includes the note:

[M]iddleware that hits request.POST should (usually) be considered a bug. It means that the view will be unable to set any custom upload handlers, perform custom parsing of the request body, or enforce permission checks prior to file uploads being accepted.