2010-03-20 11 views
5

Przeprowadzam się z tła PHP do projektu Django za pośrednictwem Pythona, głównie ze względu na walkę z MVC (lub MVT), które moim zdaniem ma największy sens, chociaż w tym wzorcu W moich poglądach zacząłem zauważać wiele powtarzających się kodów.Django - Wskazówki pozwalające uniknąć powtarzania kodu w widokach

Na przykład, po zalogowaniu mam informacje dotyczące użytkownika, który chciałbym pojawić się na każdej stronie, chociaż przy użyciu render_to_response iw każdym widoku jest to wymagane, muszę pobrać informacje i przekazać je do funkcji render_to_response .

Zastanawiam się, jaki byłby najskuteczniejszy sposób ograniczenia duplikatu kodu, który byłby w zasadzie potrzebny we wszystkich widokach w konkretnej aplikacji.

Z góry dziękuję.

Odpowiedz

4

Osobiście jestem wielkim fanem dekoratorów, które są funkcją Pythona, która nie jest specyficzna dla Django. Dekoratory są doskonałym cukrem syntaktycznym do funkcji wyższego rzędu i są szczególnie użyteczne w zmniejszaniu wymiaru znaków w widokach - możesz szybko zdefiniować uogólnioną funkcję owijania, w której możesz umieścić powtarzalny kod dla łatwego ponownego użycia i wygodnego -stop refaktoryzacji.

Najprawdopodobniej łatwiej jest Ci pokazać, niż wyjaśnić, jak działają. Oto uproszczony przykład widok:

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

... ale potem powiedzieć, że chciał, aby te strony wymagać od użytkownika, aby zalogować się może dodać kod logowania tak:.

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

.. ., który zaczyna być znacznie większy i powtarzalny, nawet dla wymyślonego przykładu. Można dokonać funkcje znowu szczupła z dekoratorów, tak:

od importu dekorator dekorator

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

Co się dzieje, jest funkcja dekorator jest wykonywany w momencie definicji funkcji. "F" w moim przykładzie to obiekt reprezentujący funkcję, do której stosuje się dekorator, który można manipulować na nieskończenie wiele sposobów.

Wymaga to decorator library, który jest darmowy dla PyPI, ponieważ znajdziesz wiele dobrych kądzików Pythona.

Nie potrzebujesz tej biblioteki do pisania funkcji dekoratora, ale jest to pomocne, szczególnie na początku. Mogą zrobić o wiele więcej - każda osoba wywołująca może być dekoratorem; możesz udekorować metody klasy i przechwycić zmienną self; dekoratorzy mogą być na łańcuchu, tak jak poniżej:

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

Zostawię poszukiwania tego, co można zrobić z takim łatwy wyższego rzędu funkcji manpipulation dla ciebie, powinno to pojęcie zaostrzy apetyt. Mam również wiele innych przykładów dla ciebie lub innych ciekawskich nowych miłośników Pythona. Powodzenia.

+1

Nawiasem mówiąc, funkcja "otagowany()" w drugim fałszywym widoku nie jest literówką; to uproszczony interfejs napisałem do aplikacji do tagowania Django, również w nazwie skrótu bojowego, co ciekawscy znajdą tutaj: http://www.djangosnippets.org/snippets/1942/ – fish2000

+0

Bardzo pomocni, dziękuję, dekoratorzy wydaje się mieć dla mnie wiele dodatkowych zastosowań. – neopickaze

5

Enkapsulacja wspólnego kodu w funkcji i wywoływanie go z różnych widoków. Brzmi banalnie, ale jest to rozwiązanie dla 99% takich potrzeb.

Aby uzyskać bardziej szczegółową odpowiedź, musisz pokazać bardziej konkretny przykład kodu, który chcesz uruchomić.

5

Istnieją dwa główne sposoby na wyodrębnienie wspólnej treści.

Context processors są najlepsze do przekazywania bitów danych, które będą potrzebne w każdym widoku.

Template tags - szczególnie tagi włączenia - są przydatne do renderowania oddzielnych obszarów strony, które będą takie same w kilku szablonach.

3

Pamiętaj też o generic views! W 90% przypadków możesz zawinąć object_list lub object_detail i zapisać sobie trochę kodu.