首页 > 解决方案 > Django 的 http.response 的 _container 属性是什么?

问题描述

我找不到一个真正试图解释它的好来源。前 5 个搜索结果只是指向源代码的不同链接。现在,我正在尝试阅读从GET请求中返回的 PDF,我想知道它为什么在 中response._container,当响应是 type 时HttpResponse。这个 PDF 是我要找的吗?为什么它是_container列表中的第二个元素?

标签: djangohttppdfdjango-rest-framework

解决方案


首先,这不是“属性”而是“属性”——在 Python 中,“属性”是实现通用计算属性支持的内置类型HttpResponse._container实际上用作HttpResponse.content属性的实现支持。

所以这是一个实现细节(正如你可以通过单个前导下划线来判断的那样),因此确实没有记录(包或框架的文档只涉及 API,而不是实现)。IOW,这里最好的文档是源代码。FWIW,源代码始终是最终文档,即使并不总是最用户友好的 ;-)

希望这部分很容易理解(来自当前主分支的代码,但这部分非常稳定):

https://github.com/django/django/blob/master/django/http/response.py#L308

class HttpResponse(HttpResponseBase):

    # ....


    @property
    def content(self):
        return b''.join(self._container)

    @content.setter
    def content(self, value):
        # Consume iterators upon assignment to allow repeated iteration.
        if hasattr(value, '__iter__') and not isinstance(value, (bytes, str)):
            content = b''.join(self.make_bytes(chunk) for chunk in value)
            if hasattr(value, 'close'):
                try:
                    value.close()
                except Exception:
                    pass
        else:
            content = self.make_bytes(value)
        # Create a list of properly encoded bytestrings to support write().
        self._container = [content]

    def __iter__(self):
        return iter(self._container)

    def write(self, content):
        self._container.append(self.make_bytes(content))

    # ...

    def writelines(self, lines):
        for line in lines:
            self.write(line)

如您所见,响应的内容作为(读/写)content属性公开,但实际上存储在_container属性中。这用于 1/ 确保内容以预期的格式存储,2/ 允许支持response.write()anditer(response)操作。

关于此处使用列表的两点:

1/ 使用列表动态构建字符串是一个非常常见的 Python 习惯用法 - 添加到列表并在最后加入它通常比连接字符串更快

2/ 这也允许使HttpResponse对象成为“类文件”对象 - HttpResponse 具有类似的closewritewritelinesflush和操作。tell__iter__

为什么它是 _container 列表中的第二个元素?

可能是因为它被写为第二个元素。


推荐阅读