【问题标题】:DRF request.data has no attribute _mutableDRF request.data 没有属性 _mutable
【发布时间】:2026-01-04 04:05:02
【问题描述】:

我正在使用 Django 2.x 和 Django REST 框架。

我使用django-oauth-toolkit 启用OAuth2 身份验证和django-rest-auth 用于登录和django-allauth 用于用户注册。

我想在用户成功注册后在响应中生成访问令牌。为此,我正在使用自定义注册视图。

为此,我创建了一个函数 utils,例如

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)

当端点被 Postman 命中时,它可以正常工作并且request.data 具有_mutable 属性。

但是当它被 Angular 应用程序命中时,它会报错

'dict' object has no attribute '_mutable'

并且错误指向mutable = request.data._mutable

为什么某些请求缺少_mutable

编辑 2:请求标头

Postman发送的请求头是

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"

来自 Angular 的请求标头是

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

编辑 3:请求类型

从端点调用的主视图是CreateAPIView。从此视图调用generate_token,该视图使用TokenView 生成访问令牌。 TokenView 使用 Django 的通用 View

【问题讨论】:

  • 你在 Angular 中执行什么 HTTP 类型的请求? GET、POST 等?
  • 它的POST。在两种情况下都使用请求标头更新了问题。
  • 您的request 对象的类型是什么? Django 的 HttpRequest 或 DRF 的 Request
  • 由于请求通过 REST 框架,其 DRF 的 Request。如果是HttpRequest,那么request.POST 将有效,而不是request.data
  • 我的意思是,您的TokenView 是什么类型的?我猜您需要切换 if 语句并将if request.data 编辑为elif request.data,因为您收到的请求可能是 django 的HttpRequest 类型。

标签: python django django-rest-framework django-rest-auth django-oauth


【解决方案1】:

为了后代(即使这个问题相当古老):

似乎 django/DRF 以不同的方式处理 multipart/form-dataapplication/json 内容类型足以导致问题。

因此,即使使用相同的端点(视图集)并且取决于表单是作为多部分还是 app/json 发送 - request.data 将是一个不同的对象。

在一种情况下,它是一个“正常”的字典,而在另一种情况下,它是QueryDict 类型。因此,为了使用 hacky _mutable on/off,需要进行类似的额外检查:

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

【讨论】:

    【解决方案2】:

    我使用过 (request.POST._mutable = True),但这种方式对我不起作用。 然后我将 request.POST 复制到一个新变量中,并在整个代码中使用了这个新变量,这样可以正常工作

    【讨论】:

      最近更新 更多