2010-03-20 10 views
5

Sto passando da uno sfondo PHP allo sviluppo di Django tramite python, principalmente per il gusto di affrontare un MVC (o MVT) che ritengo abbia più senso, anche se in questo schema Ho iniziato a notare un sacco di codice ripetuto nelle mie opinioni.Django - Suggerimenti per evitare di ripetere il codice nelle viste

Ad esempio, all'accesso ho informazioni sull'utente che vorrei apparire su ogni pagina, anche se quando uso render_to_response e in ogni vista ciò è richiesto devo prendere le informazioni e passarle alla funzione render_to_response .

Mi chiedo quale sarebbe il modo più efficiente per ridurre il codice duplicato che sarebbe essenzialmente richiesto in tutte le visualizzazioni in una particolare app.

Grazie in anticipo.

risposta

4

Personalmente sono un grande fan dei decoratori, che sono una funzione python non specifica di Django. I decoratori sono lo zucchero sintattico perfetto in aggiunta alle funzioni di ordine superiore e sono particolarmente utili per ridurre lo schema di stampa nelle viste: è possibile definire rapidamente una funzione di wrapper generalizzata, in cui è possibile inserire il codice ripetitivo per un facile riutilizzo e uno conveniente fermare il refactoring

Probabilmente è più facile mostrarti che spiegare come funzionano. Ecco un esempio di visualizzazione semplificata:

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

... ma poi detto che volevi fare queste pagine richiedono all'utente di accedere Si potrebbe aggiungere il codice di accesso in questo modo:.

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

.. che sta iniziando a diventare notevolmente più grande e ripetitivo, anche per un esempio forzato. È possibile effettuare le funzioni sottile di nuovo con decoratori, in questo modo:

da decoratore importazione decoratore

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

ciò che accade è la funzione decoratore viene eseguita al momento della definizione della funzione. La 'f' nel mio esempio è un oggetto che rappresenta la funzione a cui è applicato il decoratore, che puoi manipolare in modi infiniti.

Ciò richiede il decorator library, che è gratuito su PyPI come lo sono molti buoni bocconcini di pitone, lo troverete.

Non hai bisogno di questa libreria per scrivere le funzioni di decoratore, ma è utile, specialmente all'inizio. Possono fare molto di più - qualsiasi chiamabile può essere un decoratore; puoi decorare i metodi di classe e intercettare la variabile self; decoratori possono essere concatenati up, in questo modo:

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

Lascio l'esplorazione di ciò che si può fare con tale funzione semplice di ordine superiore manpipulation per te, dovrebbe questa nozione stuzzicare l'appetito. Ho anche molti altri esempi, per te o per qualsiasi altro curioso nuovo appassionato di pitone. In bocca al lupo.

+1

A proposito, la funzione 'tagged()' nella seconda vista falsa non è un refuso; è un'interfaccia semplificata che ho scritto sull'app django-tagging, anche nel nome della riduzione del boilerplate, che i curiosi troveranno qui: http://www.djangosnippets.org/snippets/1942/ – fish2000

+0

Molto utile, grazie, decoratori sembrano avere molti usi extra per me. – neopickaze

5

Incapsulare il codice comune in una funzione e chiamarlo da diverse viste. Sembra banale, ma è la soluzione per il 99% di tali esigenze.

Per una risposta più specifica, è necessario mostrare un esempio più concreto del codice che si desidera eseguire.

5

Esistono due modi principali per l'astrazione del contenuto comune.

Context processors sono i migliori per il passaggio di bit di dati di cui si sa che sarà necessario su ogni singola vista.

Template tags - soprattutto i tag di inclusione - sono utili per il rendering di aree separate della pagina che saranno uguali su diversi modelli.

3

Inoltre, non dimenticare di generic views! Nel 90% dei casi è possibile eseguire il wrapping di object_list o object_detail e risparmiare un po 'di codice.

Problemi correlati