2

Djangoアプリケーションには、JSONを返すビューがいくつかあり、次のような呼び出しがあります。

return HttpResponse(json.dumps(content), mimetype="application/json")

Acceptリクエストのヘッダーに応じて、HTMLまたはJSONのいずれかを返すビューの作成を開始したいと思います。おそらく他のタイプもありますが、それらが主なものです。また、このビューにルーティングされる複数のURLを取得したいと思います。ファイル拡張子「.html」と「.json」は、リクエストを行うときにクライアントにどのタイプを指定するかを指示するのに役立ちますAccept。「?format=json」アンチパターンは避けたいと思います。

最小限の定型文または繰り返しコードを使用してDjangoでこれを行うための正しい、祝福された方法は何ですか?

(編集:SOのコミュニティガイドラインに準拠するために言い換えます。)

4

3 に答える 3

2

クラスベースのビューミックスイン(django 1.3+)がこれを行う最も簡単な方法だと思います。すべてのビューは、適切なコンテンツで応答するロジックを含む基本クラスから継承されます。

于 2012-04-18T04:19:01.147 に答える
1

私はここであなたの全体像を見ていないかもしれないと思いますが、これは私がすることです:

htmlが要求されたときにレンダリングするhtmlテンプレートをjson.dumps(content)用意し、jsonが要求されたときに保持します。当たり前のようですが、とにかく言及すべきだと思いました。

"json"またはを送信するURLを設定します'html'。:

(r'^some/path/(?P<url_path>.*)\.(?P<extension>html|json)$', 'some.redirect.view'),
(r'^/(?P<extension>html|json)/AppName', include(MyApp)),
# etc etc

とあなたの見解:

def myRedirectView(request, url_path, extension):

    view, args, kwargs = resolve("/" + extension + "/" + urlPath)
    kwargs['request'] = request

    return view(*args, **kwargs)

私はそれを完全に考えていなかったので、これは少し曖昧であることを知っていますが、それは私が始めるところです。

于 2012-04-18T01:00:33.027 に答える
0

これに対処するために、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。)

于 2013-07-24T11:48:06.730 に答える