WERKZEUG中utils模块
utils是一个工具模块,很多方法都用在response和request模块中。当设计中间件的时候也需要调用某些方法。
第一个类,是一个自定义的描述符类,重构了property方法,用法相当于@property,可以参考geek范
class cached_property(property):
def __init__(self, func, name=None, doc=None):
self.__name__ = name or func.__name__
self.__module__ = func.__module__
self.__doc__ = doc or func.__doc__
self.func = func
def __set__(self, obj, value):
obj.__dict__[self.__name__] = value #设置__name__属性的值
def __get__(self, obj, type=None):
if obj is None:
return self
value = obj.__dict__.get(self.__name__, _missing)
if value is _missing:
value = self.func(obj)
obj.__dict__[self.__name__] = value
return value #获取一个实例的__name__属性,这里注意取值是obj.__dict__get().不能用self.__name__
描述的get方法,如果是属性取得属性的值,如果是返回的函数,就返回函数的地址。
class Person():
def __get__(self,attr):
if attr=='name':
return lambda:'hyperion'
s=Person()
print s.name()
上述代码返回的函数,所以需要用函数调用符号调用才能打印处函数返回值。如果不调用只能打印函数的地址。
下面分析一下HTMLBuild
class HTMLBuilder(object):
def __init__(self, dialect):
self._dialect = dialect
def __call__(self, s):
return escape(s)
def __getattr__(self, tag):
if tag[:2] == '__':
raise AttributeError(tag)
def proxy(*children, **arguments):
buffer = '<' + tag
for key, value in iteritems(arguments):
if value is None:
continue
if key[-1] == '_':
key = key[:-1]
if key in self._boolean_attributes:
if not value:
continue
if self._dialect == 'xhtml':
value = '="' + key + '"'
else:
value = ''
else:
value = '="' + escape(value) + '"'
buffer += ' ' + key + value
if not children and tag in self._empty_elements:
if self._dialect == 'xhtml':
buffer += ' />'
else:
buffer += '>'
return buffer
buffer += '>'
children_as_string = ''.join([text_type(x) for x in children
if x is not None])
if children_as_string:
if tag in self._plaintext_elements:
children_as_string = escape(children_as_string)
elif tag in self._c_like_cdata and self._dialect == 'xhtml':
children_as_string = '/*<![CDATA[*/' + \
children_as_string + '/*]]>*/'
buffer += children_as_string + '</' + tag + '>'
return buffer
return proxy
上面定义的_getattr就是返回一个函数,html = HTMLBuilder('html')
实例化,接着html.p()
就可以调用getattr中返回的函数。
接下来就是用得比较多的redirect方法:
def redirect(location, code=302, Response=None):
if Response is None:
from werkzeug.wrappers import Response
display_location = escape(location)
if isinstance(location, text_type):
from werkzeug.urls import iri_to_uri
location = iri_to_uri(location, safe_conversion=True) #将路径转换成uri
response = Response(
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n'
'<title>Redirecting...</title>\n'
'<h1>Redirecting...</h1>\n'
'<p>You should be redirected automatically to target URL: '
'<a href="%s">%s</a>. If not click the link.' %
(escape(location), display_location), code, mimetype='text/html') #调用响应response
response.headers['Location'] = location
return response
除了以上方法,还有针对模块调用的方法,以及参数认证的方法。用于在运行时确认的方法。