我已经通过创建一个基于Django自己的generic.View类的通用视图类来解决这个问题,该类定义了一个装饰器'accept_types'。这会修改应用的视图,以便在指示的内容类型不在Accept头中时返回None。然后,get()方法(其由generic.View调度员调用)看起来像这样:
def get(self, request):
self.request = request # For clarity: generic.View does this anyway
resultdata = { 'result': data, etc. }
return (
self.render_uri_list(resultdata) or
self.render_html(resultdata) or
self.error(self.error406values())
)
实际视图渲染器从而饰:
@ContentNegotiationView.accept_types(["text/uri-list"])
def render_uri_list(self, resultdata):
resp = HttpResponse(status=200, content_type="text/uri-list")
# use resp.write(...) to assemble rendered response body
return resp
@ContentNegotiationView.accept_types(["text/html", "application/html", "default_type"])
def render_html(self, resultdata):
template = loader.get_template('rovserver_home.html')
context = RequestContext(self.request, resultdata)
return HttpResponse(template.render(context))
的(一次性的)声明装饰通用视图类如下所示:
class ContentNegotiationView(generic.View):
"""
Generic view class with content negotiation decorators and generic error value methods
Note: generic.View dispatcher assigns HTTPRequest object to self.request.
"""
@staticmethod
def accept_types(types):
"""
Decorator to use associated function to render the indicated content types
"""
def decorator(func):
def guard(self, values):
accept_header = self.request.META.get('HTTP_ACCEPT',"default_type")
accept_types = [ a.split(';')[0].strip().lower()
for a in accept_header.split(',') ]
for t in types:
if t in accept_types:
return func(self, values)
return None
return guard
return decorator
(在装饰处理的参数应该一概而论 - 此代码的工作,但现在仍处于发展为我写这篇文章的实际代码是在GitHub https://github.com/wf4ever/ro-manager/tree/develop/src/roverlay/rovweb/rovserver,但在适当的时候应该分开一个单独的包。 HTH。)
同意。改写。 – Corbin 2012-04-18 00:22:01