[ADD] Request with lazy rendering support
bzr revid: fme@openerp.com-20140218161505-bmfcc2jq16vvflzn
This commit is contained in:
parent
cb03b384b0
commit
48d1e2d879
|
@ -174,6 +174,9 @@ class WebRequest(object):
|
||||||
self._cr = self.registry.db.cursor()
|
self._cr = self.registry.db.cursor()
|
||||||
return self._cr
|
return self._cr
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
return getattr(self.httprequest, attr)
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
_request_stack.push(self)
|
_request_stack.push(self)
|
||||||
return self
|
return self
|
||||||
|
@ -265,8 +268,19 @@ def route(route=None, **kw):
|
||||||
else:
|
else:
|
||||||
routes = [route]
|
routes = [route]
|
||||||
routing['routes'] = routes
|
routing['routes'] = routes
|
||||||
f.routing = routing
|
@functools.wraps(f)
|
||||||
return f
|
def response_wrap(*args, **kw):
|
||||||
|
response = f(*args, **kw)
|
||||||
|
if isinstance(response, Response) or request.func_request_type == 'json':
|
||||||
|
return response
|
||||||
|
elif isinstance(response, LazyResponse):
|
||||||
|
raise "TODO: remove LazyResponses ???"
|
||||||
|
else:
|
||||||
|
response = Response.force_type(response)
|
||||||
|
response.set_default()
|
||||||
|
return response
|
||||||
|
response_wrap.routing = routing
|
||||||
|
return response_wrap
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
class JsonRequest(WebRequest):
|
class JsonRequest(WebRequest):
|
||||||
|
@ -379,7 +393,7 @@ class JsonRequest(WebRequest):
|
||||||
mime = 'application/json'
|
mime = 'application/json'
|
||||||
body = simplejson.dumps(response)
|
body = simplejson.dumps(response)
|
||||||
|
|
||||||
r = werkzeug.wrappers.Response(body, headers=[('Content-Type', mime), ('Content-Length', len(body))])
|
r = Response(body, headers=[('Content-Type', mime), ('Content-Length', len(body))])
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def serialize_exception(e):
|
def serialize_exception(e):
|
||||||
|
@ -439,7 +453,7 @@ class HttpRequest(WebRequest):
|
||||||
def dispatch(self):
|
def dispatch(self):
|
||||||
# TODO: refactor this correctly. This is a quick fix for pos demo.
|
# TODO: refactor this correctly. This is a quick fix for pos demo.
|
||||||
if request.httprequest.method == 'OPTIONS' and request.func and request.func.routing.get('cors'):
|
if request.httprequest.method == 'OPTIONS' and request.func and request.func.routing.get('cors'):
|
||||||
response = werkzeug.wrappers.Response(status=200)
|
response = Response(status=200)
|
||||||
response.headers.set('Access-Control-Allow-Origin', request.func.routing['cors'])
|
response.headers.set('Access-Control-Allow-Origin', request.func.routing['cors'])
|
||||||
methods = 'GET, POST'
|
methods = 'GET, POST'
|
||||||
if request.func_request_type == 'json':
|
if request.func_request_type == 'json':
|
||||||
|
@ -453,7 +467,7 @@ class HttpRequest(WebRequest):
|
||||||
|
|
||||||
r = self._call_function(**self.params)
|
r = self._call_function(**self.params)
|
||||||
if not r:
|
if not r:
|
||||||
r = werkzeug.wrappers.Response(status=204) # no content
|
r = Response(status=204) # no content
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def make_response(self, data, headers=None, cookies=None):
|
def make_response(self, data, headers=None, cookies=None):
|
||||||
|
@ -470,12 +484,24 @@ class HttpRequest(WebRequest):
|
||||||
:type headers: ``[(name, value)]``
|
:type headers: ``[(name, value)]``
|
||||||
:param collections.Mapping cookies: cookies to set on the client
|
:param collections.Mapping cookies: cookies to set on the client
|
||||||
"""
|
"""
|
||||||
response = werkzeug.wrappers.Response(data, headers=headers)
|
response = Response(data, headers=headers)
|
||||||
if cookies:
|
if cookies:
|
||||||
for k, v in cookies.iteritems():
|
for k, v in cookies.iteritems():
|
||||||
response.set_cookie(k, v)
|
response.set_cookie(k, v)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def render(self, template, qcontext=None, mimetype='text/html', **kw):
|
||||||
|
""" Lazy render of QWeb template.
|
||||||
|
|
||||||
|
The actual rendering of the given template will occur at then end of
|
||||||
|
the dispatching. Meanwhile, the template and/or qcontext can be
|
||||||
|
altered or even replaced by a static response.
|
||||||
|
|
||||||
|
:param basestring template: template to render
|
||||||
|
:param dict qcontext: Rendering context to use
|
||||||
|
"""
|
||||||
|
return Response(template=template, qcontext=qcontext, mimetype=mimetype, **kw)
|
||||||
|
|
||||||
def not_found(self, description=None):
|
def not_found(self, description=None):
|
||||||
""" Helper for 404 response, return its result from the method
|
""" Helper for 404 response, return its result from the method
|
||||||
"""
|
"""
|
||||||
|
@ -892,6 +918,42 @@ mimetypes.add_type('application/font-woff', '.woff')
|
||||||
mimetypes.add_type('application/vnd.ms-fontobject', '.eot')
|
mimetypes.add_type('application/vnd.ms-fontobject', '.eot')
|
||||||
mimetypes.add_type('application/x-font-ttf', '.ttf')
|
mimetypes.add_type('application/x-font-ttf', '.ttf')
|
||||||
|
|
||||||
|
class Response(werkzeug.wrappers.Response):
|
||||||
|
""" Response object passed through controller route chain.
|
||||||
|
|
||||||
|
In addition to the werkzeug.wrappers.Response parameters, this
|
||||||
|
classe's constructor can take the following additional parameters
|
||||||
|
for QWeb Lazy Rendering.
|
||||||
|
|
||||||
|
:param basestring template: template to render
|
||||||
|
:param dict qcontext: Rendering context to use
|
||||||
|
:param int uid: User id to use for the ir.ui.view render call
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, **kw):
|
||||||
|
template = kw.pop('template', None)
|
||||||
|
qcontext = kw.pop('qcontext', None)
|
||||||
|
uid = kw.pop('uid', None)
|
||||||
|
self.set_default(template, qcontext, uid)
|
||||||
|
super(Response, self).__init__(*args, **kw)
|
||||||
|
|
||||||
|
def set_default(self, template=None, qcontext=None, uid=None):
|
||||||
|
self.template = template
|
||||||
|
self.qcontext = qcontext or dict()
|
||||||
|
self.uid = uid
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_qweb(self):
|
||||||
|
return self.template is not None
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
view_obj = request.registry["ir.ui.view"]
|
||||||
|
uid = self.uid or request.uid or openerp.SUPERUSER_ID
|
||||||
|
return view_obj.render(request.cr, uid, self.template, self.qcontext, context=request.context)
|
||||||
|
|
||||||
|
def flatten(self):
|
||||||
|
self.response.append(self.render())
|
||||||
|
self.template = None
|
||||||
|
|
||||||
class LazyResponse(werkzeug.wrappers.Response):
|
class LazyResponse(werkzeug.wrappers.Response):
|
||||||
""" Lazy werkzeug response.
|
""" Lazy werkzeug response.
|
||||||
API not yet frozen"""
|
API not yet frozen"""
|
||||||
|
@ -1039,6 +1101,7 @@ class Root(object):
|
||||||
return HttpRequest(httprequest)
|
return HttpRequest(httprequest)
|
||||||
|
|
||||||
def get_response(self, httprequest, result, explicit_session):
|
def get_response(self, httprequest, result, explicit_session):
|
||||||
|
# TODO: Remove LazyResponse
|
||||||
if isinstance(result, LazyResponse):
|
if isinstance(result, LazyResponse):
|
||||||
try:
|
try:
|
||||||
result.process()
|
result.process()
|
||||||
|
@ -1048,8 +1111,17 @@ class Root(object):
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
if isinstance(result, Response) and result.is_qweb:
|
||||||
|
try:
|
||||||
|
result.flatten()
|
||||||
|
except(Exception), e:
|
||||||
|
if request.db:
|
||||||
|
result = request.registry['ir.http']._handle_exception(e)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
if isinstance(result, basestring):
|
if isinstance(result, basestring):
|
||||||
response = werkzeug.wrappers.Response(result, mimetype='text/html')
|
response = Response(result, mimetype='text/html')
|
||||||
else:
|
else:
|
||||||
response = result
|
response = result
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue