6

私はPHPのバックグラウンドからPythonを介してDjango開発に移行しています。主に、最も理にかなっていると思うMVC(またはMVT)に取り組むためですが、このパターンでは、私の見解。

たとえば、ログインすると、すべてのページに表示したいユーザーに関する情報がありますが、render_to_responseを使用する場合、すべてのビューでこれが必要ですが、情報を取得して、render_to_response関数に渡す必要があります。

特定のアプリのすべてのビューで本質的に必要となる重複コードを削減するための最も効率的な方法は何でしょうか。

前もって感謝します。

4

4 に答える 4

7

個人的には、Djangoに固有ではないPython機能であるデコレータの大ファンです。デコレータは、高階関数に加えて完璧なシンタックスシュガーであり、ビューのボイラープレートを減らすのに特に役立ちます。一般化されたラッパー関数をすばやく定義できます。この関数では、繰り返しコードを配置して、簡単に再利用でき、便利なものにすることができます。 -リファクタリングを停止します。

それらがどのように機能するかを説明するよりも、おそらくあなたに見せることの方が簡単です。簡略化したビューの例を次に示します。

def listpage(request):
    return HttpResponse(render_to_string("itemlist.html", {
        "items": Item.objects.filter(visible=True).order_by("-modifydate")
    }))

def itemlist_tags(request, tags):
    return HttpResponse(render_to_string("itemlist.html", {
        "items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
    }))

...しかし、これらのページでユーザーがログインする必要があるようにしたいとします。次のようにログインコードを追加できます。

def listpage(request):
    if not request.user.is_authenticated():
        return f(request, *args, **kwargs)
    else:
        return HttpResponse(render_to_string("itemlist.html", {
            "items": Item.objects.filter(visible=True).order_by("-modifydate")
        }))

def itemlist_tags(request, tags):
    if not request.user.is_authenticated():
        return f(request, *args, **kwargs)
    else:
        return HttpResponse(render_to_string("itemlist.html", {
            "items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
        }))

...これは、不自然な例であっても、著しく大きく、反復的になり始めています。次のように、デコレータを使用して関数を再びスリムにすることができます。

デコレータからインポートデコレータ

@decorator
def loginrequired(f, request, *args, **kwargs):
    if request.user.is_authenticated():
        return f(request, *args, **kwargs)
    else:
        return HttpResponseRedirect("/")

@loginrequired
def listpage(request):
    return HttpResponse(render_to_string("itemlist.html", {
        "items": Item.objects.filter(visible=True).order_by("-modifydate")
    }))

    @loginrequired
def itemlist_tags(request, tags):
    return HttpResponse(render_to_string("itemlist.html", {
        "items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
    }))

@loginrequired
def another_such_function(request):
    (...)

@loginrequired
def and_again(request):
    (...)

デコレータ関数は、関数の定義時に実行されます。私の例の「f」は、デコレータが適用される関数を表すオブジェクトであり、無限の方法で操作できます。

これにはデコレータライブラリが必要です。これは、多くの優れたpython morselsと同様に、PyPIでは無料です。

デコレータ関数を作成するためにこのライブラリは必要ありませんが、特に最初は便利です。彼らはもっとたくさんのことをすることができます-どんな呼び出し可能なものもデコレータになることができます。クラスメソッドを装飾し、self変数をインターセプトできます。デコレータは、次のようにチェーン化できます。

@second
@first
def originalfunction(*args):
    (...)

この概念があなたの食欲を刺激した場合、私はあなたがそのような簡単な高階関数の操作で何ができるかについての探求をあなたに任せます。あなたや他の好奇心旺盛な新しいPython愛好家のために、さらに多くの例があります。幸運を。

于 2010-03-20T21:54:23.323 に答える
5

共通コードを関数にカプセル化し、さまざまなビューから呼び出します。些細なことのように聞こえますが、それはそのようなニーズの99%の解決策です。

より具体的な答えを得るには、実行するコードのより具体的な例を示す必要があります。

于 2010-03-20T09:43:15.033 に答える
5

一般的なコンテンツを抽象化するには、主に2つの方法があります。

コンテキストプロセッサは、すべてのビューで必要になることがわかっているデータのビットを渡すのに最適です。

テンプレートタグ(特に包含タグ)は、複数のテンプレートで同じになるページの個別の領域をレンダリングするのに役立ちます。

于 2010-03-20T10:15:53.637 に答える
3

また、一般的なビューも忘れないでください。90%の場合、object_listまたはobject_detailをラップして、コードを保存できます。

于 2010-03-20T15:04:05.413 に答える