これに対処するために、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))
デコレータを宣言する(1回限りの)ジェネリックビュークラスは次のようになります。
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。)