1

I have this model and resource for user-profile

class Profile(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(blank=False, null=False, unique=True)
    avatar = models.ImageField(blank=True, null=True)

class ProfileResource(ModelResource):
    class Meta:
        queryset = Profile.objects.all()
        resource_name = 'profiles'
        allowed_methods = ['get', 'patch']

When I had try to patch this resource, i got the exception:

RawPostDataException("You cannot access body after reading from request's data stream")

For sending test data I use the chrome-extention

send the PATHC query to my resource

Dmitry
  • 551
  • 6
  • 19

2 Answers2

1

This is related to the file upload that you are trying to do. The content type cannot be processed in this way, you should convert the file to base64 in order to do that.

Check this Github issue for further information on how you should proceed on POST (or PATCH) files to your resource.

Also, this stack is related to your problem.

Community
  • 1
  • 1
silviomoreto
  • 5,629
  • 3
  • 30
  • 41
0

It was one of the issues in DRF(django-rest-framework) you can check on GitHub of Tom Christie. Issue was closed with the solution given below. You can also find same solution on issues page of djang-rest-framework repository

For various reasons, Django only allows reading POST body once. Since the body is exposed with a file-like API, you can't easily read the file again. Also, you won't be able to change upload file handlers if you have already read the data. Failing to read POST data only once will fail, and it is tricky to debug for two reasons.

  • Django only reports its error the second time you access the body, so it can be difficult to track the first time it was accessed.
  • A myriad of different issues may cause this. One way is to print the full traceback (with traceback.print_stack()) whenever the data gets read (in django/http/request.py: HttpRequest.read and HttpRequest.readline). This is how I did it, maybe there are other ways.

So, did you access request.method somewhere in your code? Are you using Django test client? If so, it's possible that HTTP header based method overriding kicked in. This feature allows browsers to simulate requests other than GET/POST. To do so, django-rest-framework looks at hidden form fields such as <input type="hidden" name="_method" value="DELETE">. With POST requests, this information is in the request body, so django-rest-framework will have to read the request body.

This feature is enabled by default, but django-rest-framework ensures that the

request is indeed POST and is indeed using a Content-Type that would be sent on a form submission.

But that's exactly the behavior of Django test client! Two possible fixes exist:

Disable browser overrides

REST_FRAMEWORK = {
'FORM_METHOD_OVERRIDE': None,
'FORM_CONTENT_OVERRIDE': None,
'FORM_CONTENTTYPE_OVERRIDE': None
 }

Change the Content-Type in Django test client

 from django.test import Client

 client = Client()
 response = client.post(url, content_type='application/json')
Prashant Shukla
  • 742
  • 2
  • 6
  • 19