Django - HttpRequest类的代码

0 投票
1 回答
856 浏览
提问于 2025-04-17 17:13

回答

(1)
HttpRequest对象的read()方法会调用它的_stream属性中的read()方法。也就是说,_stream是一个自己的对象,它有自己的read()方法。

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

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

(4)
没错。更准确地说,@property装饰器的意思是,当我们引用这个名字时,比如self.body,这个方法就会被调用。

/感谢Daniel Roseman提供的答案。/


问题

我正在查看Django的HttpRequest类的代码。

根据下面的代码,self.body()尝试调用self.read()并将返回值赋给self._body
如果没有异常,它会在self._body上调用StringIO,并将返回值赋给self._stream

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

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

(3)
根据我在HttpRequest的定义中找到的,self._stream是由self.body方法创建的。
当第一次调用self.body()时会发生什么?假设self._stream还没有被创建。
为了创建它,self.body()需要先创建self._body
为了创建self._body,调用了self.read()
但是,self.read()又调用了self._stream上的read()
那么,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)

    #...

1 个回答

0
  1. 不,这里调用的是 self._stream 这个对象的 read() 方法。

  2. 这是一个常见的写法,可以让你在方法里传入任意数量的参数(包括位置参数和关键字参数)。在这个例子中,这些参数会直接传给流的读取方法。

  3. 在那段代码上方的注释解释了发生了什么——self._stream 必须在子类中设置。

  4. 没错。@property 装饰器的意思是,当你只提到这个名字时,方法会被调用,比如 self.body,而不是 self.body()

撰写回答