Django - HttpRequest类的代码
回答
(1)
HttpRequest
对象的read()
方法会调用它的_stream
属性中的read()
方法。也就是说,_stream
是一个自己的对象,它有自己的read()
方法。
(2)
HttpRequest
对象和_stream
的read()
方法不一定和文件对象的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
的定义中包含args
和kwargs
的原因是什么?
(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 个回答
不,这里调用的是
self._stream
这个对象的read()
方法。这是一个常见的写法,可以让你在方法里传入任意数量的参数(包括位置参数和关键字参数)。在这个例子中,这些参数会直接传给流的读取方法。
在那段代码上方的注释解释了发生了什么——
self._stream
必须在子类中设置。没错。
@property
装饰器的意思是,当你只提到这个名字时,方法会被调用,比如self.body
,而不是self.body()
。