【问题标题】:Modify value of body in django request在 django 请求中修改 body 的值
【发布时间】:2020-08-04 22:14:55
【问题描述】:

我想在我的 django API(也使用 rest 框架)中更新 post Request 中 json body 值的值,现在我正在尝试使用自定义中间件来执行此操作。这是我的中间件。

def CustomMiddleware(get_response):
    def middleware(request):

        print('request: ', request, ' type: ', type(request), ' vars: ', vars(request))
        print('request: ', request.body)
        body = json.loads(request.body)
        body['attr'] = str(body['attr'])+'abc'
        request.body = json.dumps(body)
        response = get_response(request)
        return response

return middleware

所以当我向我的 API 发出 POST 请求时,我收到了这个错误:

File "/path/models_masking/mask_middleware.py", line 37, in middleware
    request.body = json.dumps(request_updated)
AttributeError: can't set attribute

我阅读并发现 request 对象是不可变的,所以我不确定我是否能够复制到请求对象,修改副本然后将其发送到 get_response 函数,或者也许有更好的方法来做到这一点,也许是我的 APIView 类的装饰器。

谁能帮我解决这个问题?

编辑

'attr'+'abc' 的值是在代码库的许多部分中使用的新值,我的核心问题是我不想在很多函数中更改该值在很多请求端点中,所以我的第一个想法是更新请求的值以在所有请求中自动更改“attr”的值,而不是更新每个请求。

这可能是一个新问题,但如果有人能为我的问题提供更好的解决方案,我将不胜感激。

【问题讨论】:

  • 为什么要这么做,能给个示例视图吗?
  • 更改请求的正文看起来很“奇怪”。 HttpRequest 不是完全不可变的,例如 .user 是由中间件添加的。但是,更改请求正文看起来很“奇怪”。
  • 您确定不想对每个请求都执行此操作吗?
  • @IainShelvington 是的,基本上请求中的数据是以某种方式被加密的,实际上在许多请求中,我不想在我认为的所有 POST 或 PUT 函数中手动解密,那就是为什么我试图在中间件中更改身体的数据。
  • @IainShelvington 一个视图就像 ``` from models import Person class MyView(APIView): def post(self, request, *args, **kwargs): # this attr var will be the concat with 'abc' attr = request.body['attr'] Person.objects.get(attr=attr) ```

标签: django python-3.6 django-middleware


【解决方案1】:

我同意其他人的说法,更改请求的正文并不常见,但如果你真的需要,那么你可以设置request._body,因为body 只是一个属性

    @property
    def body(self):
        if not hasattr(self, '_body'):
            if self._read_started:
                raise RawPostDataException("You cannot access body after reading from request's data stream")

            # Limit the maximum request data size that will be handled in-memory.
            if (settings.DATA_UPLOAD_MAX_MEMORY_SIZE is not None and
                    int(self.META.get('CONTENT_LENGTH') or 0) > settings.DATA_UPLOAD_MAX_MEMORY_SIZE):
                raise RequestDataTooBig('Request body exceeded settings.DATA_UPLOAD_MAX_MEMORY_SIZE.')

            try:
                self._body = self.read()
            except IOError as e:
                raise UnreadablePostError(*e.args) from e
            self._stream = BytesIO(self._body)
        return self._body

【讨论】:

  • 非常感谢@James,这实际上适用于我的问题。我觉得修改请求的正文很奇怪,那是因为我包括了我的部分问题,如果可能有更好的方法来做到这一点,但也许我不是很清楚,将使用修改后的“attr”值在代码库的另一个过程中,我不想修改所有函数来修改'attr'的值然后使用,这就是为什么我要更改请求正文,实际上对于很多请求我需要这个'attr' 已修改。再说一遍,也许您可​​以为我的问题提供更好的解决方案?
  • @juancsr 是的,我知道你的意思。
  • 所以基本上attr 是'123',该请求背后的过程是我需要'123abc'而不是'123',这对于我的应用程序中的很多请求基本相同,所以我不想在每个函数中手动更改attr 的值,我正在寻找一种方法来自动为我的应用程序请求执行此操作。
  • 尝试全局变量或单例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-06
  • 2015-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多