简体   繁体   中英

DRF request.data has no attribute _mutable

I'm using Django 2.x and Django REST framework.

I'm using django-oauth-toolkit to enable OAuth2 authentication and django-rest-auth for login and django-allauth for user registration.

I want to generate access token in the response when a user is successfully registered. For that, I'm using a custom registration view.

For that, I have created a function utils like

def generate_token(request, user):
    # Get OAuth application to use
    application_: Application = Application.objects.filter(
        client_type=Application.CLIENT_CONFIDENTIAL,
        authorization_grant_type=Application.GRANT_PASSWORD
    ).first()

    if not application_:
        raise Exception('No OAuth2 Application is setup')

    auth_data = {
        'username': user.username,
        'password': password,
        'grant_type': 'password',
        'client_id': application_.client_id,
        'client_secret': application_.client_secret
    }

    if request.data:

        mutable = request.data._mutable
        request.data._mutable = True
        request.data.update(auth_data)
        request.data._mutable = mutable

    if request.POST:
        mutable = request.POST._mutable
        request.POST._mutable = True
        request.POST.update(auth_data)
        request.POST._mutable = mutable

    return TokenView().create_token_response(request=request)

When the endpoint is hit by Postman it works fine and request.data has _mutable attribute.

But when it is hit by Angular application, it gives error

'dict' object has no attribute '_mutable'

and the error points to mutable = request.data._mutable

Why _mutable is missing for some requests?

Edit 2: Request headers

The request header sent by Postman is

Content-Type:"application/json"
Accept:"application/json, text/plain, /"
User-Agent:"PostmanRuntime/7.15.2"
Cache-Control:"no-cache"
Postman-Token:"b4461728-a6a9-48da-a4fa-3894920b5484"
Host:"api.staging.scanova.io"
Cookie:"messages="660481c3ce8c48b1884641ffdec0a3f701cdc9cf$..."; csrftoken=tNa6o6RDkEUTBti1cDJCvgV5oLG84qczgADeDfSY7hROsLP6cmhIgQKaamPQU7Xy; sessionid=r0l8kh58n8i14quyemj60ur6i59uhy1i"
Accept-Encoding:"gzip, deflate"
Content-Length:635
Connection:"keep-alive"

The request header from Angular is

Accept: application/json, text/plain, */*
Authorization: false false
Content-Type: application/json
Origin: https://localhost:4200
Referer: https://localhost:4200/auth/register
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36

Edit 3: Request type

The main view which is called from the endpoint is CreateAPIView . generate_token is called from this view which uses TokenView to generate an access token. The TokenView use Django's generic View .

For posterity (even though the question is rather old):

It seems like django/DRF treats multipart/form-data and application/json content type in a different enough way to cause issues.

So, even when using the same endpoint(viewset) and depending on whether the form is sent as multipart or app/json - request.data will be a different object.

In one case it would be a 'normal' dict while in other it would be of QueryDict type. So, in order to use the hacky _mutable on/off an additional check similar to this is needed:

...
# one can also use:
# if 'multipart/form-data' in request.META.get('CONTENT_TYPE'):
# instead of the condition below
if isinstance(request.data, QueryDict):
  auth_data = json.dumps(auth_data) # <----- QueryDict expects string values

request.POST._mutable = True # <----- mutable needs to be modified on POST and not on data
request.data.update(auth_data)
request.POST._mutable = False
...

I used (request.POST._mutable = True) and this way does not work for me. then I copied request.POST in a new variable and I use the new variable in whole my code and this way work fine

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM