【问题标题】:Django - code of HttpRequest classDjango - HttpRequest 类的代码
【发布时间】:2013-02-26 19:37:06
【问题描述】:

回答

(1)
HttpRequest 对象 (self) 的 read() 方法调用其 _stream 属性的 read() 方法。 也就是说,_stream 是它自己的类的对象,并且有自己的 read() 方法。

(2)
HttpRequest 对象和_streamread() 方法不一定与文件对象的read() 相同。因此,它们可能采用不同的参数。

(3)
self._stream 必须由子类设置。

(3)
是的。更准确地说,@property 装饰器意味着每当我们引用该方法时都会调用该方法
名称,例如self.body

/感谢 Daniel Roseman 的回答。/


问题

我正在浏览 Django 的 HttpRequest 类的代码。

根据下面的代码,self.body() 尝试调用self.read() 并将其返回值分配给self._body
如果没有例外,它会在 self._body 上调用 StringIO 并将其返回值分配给 self._stream。

我有四个相关问题:
(1)
self.read() 是否在 self._stream 上调用自己?还是调用文件对象的读取方法?

(2)
self.read 的定义中包含 args 和 kwargs 的原因是什么?

(3)
对于我在 HttpRequest 的定义中发现的内容,self._stream 是由 self.body 方法创建的。
第一次调用self.body() 时会发生什么?据推测,self._stream 尚未创建。
要创建它,self.body() 需要先创建self._body
要创建 self._body,调用 self.read()。
但是 self.read() calls .read() on self._stream.
那么,它从哪里获得 self._stream?

(4)
不管 self.body 是一个属性,还是调用 self.body() 方法,
它的返回值就是我们调用 self.body 时得到的。我说的对吗?

django.http.HttpRequest

class HttpRequest(object):

    #...

    def __init__(self):
        self.GET, self.POST, self.COOKIES, self.META, self.FILES = {}, {}, {}, {}, {}
        self.path = ''
        self.path_info = ''
        self.method = None
        self._post_parse_error = False

    #...

    @property
    def body(self):
        if not hasattr(self, '_body'):
            if self._read_started:
                raise Exception("You cannot access body after reading from request's data stream")
            try:
                self._body = self.read()
            except IOError, e:
                raise UnreadablePostError, e, sys.exc_traceback
            self._stream = StringIO(self._body)
        return self._body

    #...

    def read(self, *args, **kwargs):
        self._read_started = True
        return self._stream.read(*args, **kwargs)

    #...

【问题讨论】:

    标签: python django python-2.7 django-views


    【解决方案1】:
    1. 不,它调用 read() 的任何对象 self._stream 的方法。

    2. 这是允许将任意参数(位置和关键字)传递给方法的正常模式。在这种情况下,它们会直接传递给流的读取方法。

    3. 该代码上方的注释解释了发生了什么 - self._stream 必须由子类设置。

    4. 是的。 @property 装饰器意味着当您仅引用名称时调用该方法,即使用self.body 而不是self.body()

    【讨论】:

    • 1. read() 不只接受一个(大小)参数吗?它与我们打开文件时使用的 read() 方法不一样吗?如果是这样,称它为“self._stream.read(size)”还不够吗?
    • 不一定:正如我所说,它是read 的任何self._stream 的方法。从上面的代码来看,这是一个 StringIO 实例,在这种情况下它采用相同的参数 - 但没有什么可以阻止子类使用完全不同的类,它可能会为其 read 方法提供更多参数。
    • 我现在明白了。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    相关资源
    最近更新 更多