如何在django REST框架中修改request.data

Joh*_*aff 18 python django json django-rest-framework

我正在使用Django REST Framework

request.data = '{"id": "10", "user": "tom"}'
Run Code Online (Sandbox Code Playgroud)

我想"age": "30"在发送它之前添加额外的属性

    request.data = new_data
    response = super().post(request, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

我有两个问题

  1. 为什么request.data是字符串而不是字典
  2. 我如何更新request.data

Ibr*_*eer 16

如果您的 API 是APIView那么您应该使用更新函数来扩展您的请求数据对象,而不会丢失从客户端发送的数据。

request.data.update({"id": "10", "user": "tom"})
Run Code Online (Sandbox Code Playgroud)

  • AttributeError:此 QueryDict 实例是不可变的 (5认同)

Ste*_*iov 8

一个好朋友刚刚用比我上面说明的更简单的方法带我去学校

class CreateSomething(CreateAPIView):
    model = Something
    queryset = Something.objects.all()
    serializer_class = SomethingSerializer

    perform_create(self,serializer):
    def perform_create(self,serializer):
        ip = self.get_ip()
        ## magic here: add kwargs for extra fields to write to db
        serializer.save(ip_addr=ip)

    def get_ip(self):
        x_forwarded_for = self.request.META.get('HTTP_X_FORWARDED_FOR',None)
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = self.request.META.get('REMOTE_ADDR',None)
        return ip

class SomethingSerializer(serializers.ModelSerializer):
    email = serializers.EmailField(validators=[UniqueValidator(queryset=Something.objects.all())])
    fieldA = serializers.CharField()
    fieldB = serializers.CharField()

    class Meta:
        model = Customer2
        fields = ['email','fieldA','fieldB','ip_addr']
        read_only_fields = ['ip_addr']
Run Code Online (Sandbox Code Playgroud)

  • 很遗憾没有更直观的方法来做到这一点。可能是更好的 mixin 或一些预定义的函数。 (3认同)

val*_*ame 8

通常request在 drf 视图中是rest_framework.request.Request实例。其源代码如下(djangorestframework==3.8.2):

    @property
    def data(self):
        if not _hasattr(self, '_full_data'):
            self._load_data_and_files()
        return self._full_data
Run Code Online (Sandbox Code Playgroud)

你可以做:

request._full_data = your_data
Run Code Online (Sandbox Code Playgroud)


mik*_*dge 6

request.data应该是一个不可变的QueryDict,而不是一个字符串。如果需要修改:

if isinstance(request.data, QueryDict): # optional
    request.data._mutable = True
request.data['age'] = "30"
Run Code Online (Sandbox Code Playgroud)

您可能会检查它是否是 的实例的唯一原因QueryDict是使用常规dict.


Ste*_*ney 2

它看起来像一个 json 字符串。要将其转换为字典,您应该执行以下操作:

import json
data = json.loads(request.data)
Run Code Online (Sandbox Code Playgroud)

然后你可以添加额外的属性:

data['age'] = 30
Run Code Online (Sandbox Code Playgroud)

然后您将不得不提出新的请求,因为您似乎无法仅更改旧的请求。这假设您要发布到 /notes/:

from rest_framework.test import APIRequestFactory
factory = APIRequestFactory()
request = factory.post('/notes/', data, format='json')
Run Code Online (Sandbox Code Playgroud)