2010-03-20 4 views
5

Ich bin von einem PHP-Hintergrund in Django Entwicklung über Python bewegt, vor allem für die MVC (MVT), die ich fühle am sinnvollsten, obwohl in diesem Muster Ich habe eine Menge Code in meinen Ansichten bemerkt. Wenn ich zum Beispiel eingeloggt bin, habe ich Informationen über den Benutzer, der auf jeder Seite erscheinen soll. Wenn ich render_to_response benutze und dies in jeder Ansicht erforderlich ist, muss ich die Informationen abrufen und sie an die render_to_response-Funktion übergeben .Django - Tipps zur Vermeidung von Code in Sichten zu wiederholen

Ich frage mich, was wäre der effizienteste Weg, um den doppelten Code, der im Wesentlichen in allen Ansichten in einer bestimmten App erforderlich wäre zu reduzieren.

Vielen Dank im Voraus.

Antwort

4

Persönlich bin ich ein großer Fan von Decorators, die eine Python-Funktion sind, die nicht spezifisch für Django ist. Decorators sind der perfekte syntaktische Zucker zusätzlich zu Funktionen höherer Ordnung, und sie sind besonders nützlich zum Reduzieren von Boilerplate in Views - Sie können schnell eine verallgemeinerte Wrapper-Funktion definieren, in der Sie den repetitiven Code für die einfache Wiederverwendung und bequeme setzen können -stop Refactoring.

Es ist wahrscheinlich einfacher, Ihnen zu zeigen, wie sie funktionieren. Hier ist eine vereinfachte Ansicht Beispiel:

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"), 
    })) 

... aber dann sagen Sie diese Seiten muss der Benutzer machen wollte eingeloggt Sie können Login-Code hinzufügen, etwa so:.

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"), 
     })) 

.. Es beginnt merklich größer und repetitiv zu werden, selbst für ein künstliches Beispiel. Sie können Ihre Funktionen schlank wieder mit Dekorateure, wie so machen:

von Dekorateur Import Dekorateur

@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): 
    (...) 

Was die Dekorateur Funktion ausgeführt wird zum Zeitpunkt der Funktionsdefinition geschieht ist. Das 'f' in meinem Beispiel ist ein Objekt, das die Funktion darstellt, auf die der Dekorator angewendet wird und die Sie auf endlose Weise manipulieren können.

Dies erfordert die decorator library, die auf PyPI frei ist, wie viele gute Python Bissen, finden Sie.

Sie brauchen diese Bibliothek nicht, um Dekorationsfunktionen zu schreiben, aber es ist hilfreich, besonders am Anfang. Sie können viel mehr tun - jeder Anrufer kann ein Dekorateur sein; Sie können Klassenmethoden dekorieren und die self Variable abfangen; Dekorateure können, wie so angekettet werden:

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

Ich werde die Erforschung lassen, was man mit so einfachen Funktion höherer Ordnung manpipulation für Sie tun können, sollte dieser Begriff Ihren Appetit anregen. Ich habe noch viele weitere Beispiele für Sie oder andere neugierige neue Python-Liebhaber. Viel Glück.

+1

Übrigens ist die 'tagged()' Funktion in der zweiten gefälschten Ansicht kein Tippfehler; Es ist eine vereinfachte Schnittstelle, die ich an die Django-Tagging-App geschrieben habe, auch im Namen von Boilerplate-Reduktion, die die Neugierigen hier finden: http://www.djangosnippets.org/snippets/1942/ – fish2000

+0

Sehr hilfreich, danke, Dekorateure scheinen für mich eine Menge extra Nutzen zu haben. – neopickaze

5

Den gemeinsamen Code in einer Funktion einkapseln und aus verschiedenen Ansichten aufrufen. Klingt trivial, aber es ist die Lösung für 99% solcher Bedürfnisse.

Für eine genauere Antwort müssen Sie ein konkreteres Beispiel für den Code zeigen, den Sie ausführen möchten.

5

Es gibt zwei Möglichkeiten, den gemeinsamen Inhalt zu abstrahieren.

Context processors eignen sich am besten für die Weitergabe von Daten, von denen Sie wissen, dass sie in jeder einzelnen Ansicht benötigt werden.

Template tags - besonders Einschluss Tags - sind nützlich für die Wiedergabe von separaten Bereichen der Seite, die auf mehreren Vorlagen identisch sein wird.

3

Vergessen Sie auch nicht generic views! In 90% der Fälle können Sie object_list oder object_detail umbrechen und sich Code sparen.