2013-02-11 13 views
8

Przed widokami opartymi na klasach było słowo kluczowe extra_context, które można przekazać w urlsconf. https://docs.djangoproject.com/en/1.3/topics/generic-views/#adding-extra-contextwidok ogólny oparty na klasie dodatkowy kontekst

Teraz z ogólnych poglądów na bazie klasy, jeśli chcemy zrobić to samo mamy do podklasy widoku Generic https://docs.djangoproject.com/en/1.3/topics/class-based-views/#adding-extra-context

Jeśli chcemy coś prostego, a my za pomocą rodzajowe CreateView i UpdateView. To podejście wymusi na podklasie coś, co wcześniej było banalne. Co więcej, musimy złamać zasadę DRY, robiąc to dwa razy.

Dlaczego tak jest? Czy istnieje jakiś powód, dla którego nie możemy przekazać dodatkowego kontekstu bezpośrednio do szablonu?

Dzięki

Odpowiedz

13

Po zbyt wielu myślach, jedyną odpowiedzią jest NIE, że funkcja została usunięta.

Dokumentacja nie wspomina o "usuniętej funkcji" i nie ma wyjaśnienia, dlaczego tak było.

Ale co moje życie łatwiejsze Wziąłem porady od @aidan i modyfikowane trochę

class ExtraContext(object): 
    extra_context = {} 

    def get_context_data(self, **kwargs): 
     context = super(ExtraContext, self).get_context_data(**kwargs) 
     context.update(self.extra_context) 
     return context 

class ExtraListView(ExtraContext, ListView): 
    pass 

class ExtraDetailView(ExtraContext, DetailView): 
    pass 

class ExtraUpdateView(ExtraContext, UpdateView): 
    pass 

class ExtraCreateView(ExtraContext, CreateView): 
    pass 

class ExtraDeleteView(ExtraContext, DeleteView): 
    pass 

class ExtraCloneView(ExtraUpdateView): 
    def post(self, request, *args, **kwargs): 
     return ExtraCreateView.as_view(model=self.model, 
           template_name=self.template_name, 
           extra_context=self.extra_context)(request, *args, **kwargs)  

Teraz mam pół-rodzajowe widoki, które można użyć bezpośrednio w URLSconf i przekazać extra_context dict do as_view() zadzwonić

url(r'^camera/(?P<pk>\d+)/$', 
    views.ExtraDetailView.as_view(model=models.Camera, 
           extra_context={'action_type': 'detail', 'mod_name' : 'camera'}, 
           template_name='cameras/camera_detail.html'), 
    name='camera_detail'), 
+0

Cieszę się, że mogłem pomóc. –

+0

Bardzo dziękuję za to rozwiązanie. Zrobiłem prawie cały mój projekt oparty na klasycznych ogólnych widokach na adresy URL, a bez tego musiałbym zmienić wszystko. – guinunez

8

Chyba nie jest aż tak proste, ale to wciąż tylko 5 linii kodu -

class MyView(CreateView): 
    def get_context_data(self, *args, **kwargs): 
     context = super(MyView, self).get_context_data(*args, **kwargs) 
     context['my_additional_context'] = my_object 
     return context 

Jeśli naprawdę chcesz tę funkcjonalność z widokiem na bazie klasy, to może można przedłużyć Klasa je dodać -

class MyCreateView(CreateView) 
    additional_context = {} 
    def get_context_data(self, *args, **kwargs): 
     context = super(MyView, self).get_context_data(*args, **kwargs) 
     context.append(self.additional_context) 
     return context 

następnie używać go w swojej url_conf -

urlpatterns = patterns('', 
    #.... 
    (r'^my_url/$', MyCreateView.as_view(additional_context={'my_addional_context': my_object})), 
) 

Możesz napisać własny CreateView, DetailView, ListView itp. I zaimportować je do każdego projektu, który zrobisz.

+0

Problem polega nie na tym, jak wykonać podklasę ogólnych widoków, problem polega na tym, że ta funkcja została usunięta. – fariza

+0

Tak, chyba. Naprawdę nie mam odpowiedzi na twoje pytanie. Nie wiem, dlaczego został usunięty. –

+0

to zadziała, ale jest stara reguła Django "Nie przekazuj niczego, aby url widoki w pliku url!" to sprawi, że będzie wolniej!zasób z dwóch miarek django (książka) –

5

Czytając powyższe odpowiedzi, wydawało się, że to podejście, przy rozwiązywaniu problemu, był zasadniczo hack przywrócić starą funkcjonalność. Nieco googling podniósł generic class-based views page, który zawiera sekcję zatytułowaną "adding extra context." Wystarczy, aby podsumować tutaj, rozwiązaniem jest po prostu zaimplementować własną wersję get_context_data() które obejmowałyby zmienne, które chcesz przekazać do szablonów:

from django.views.generic import DetailView 
from books.models import Publisher, Book 

class PublisherDetail(DetailView): 

    model = Publisher 

    def get_context_data(self, **kwargs): 
     # Call the base implementation first to get a context 
     context = super(PublisherDetail, self).get_context_data(**kwargs) 
     # Add in a QuerySet of all the books 
     context['book_list'] = Book.objects.all() 
     return context 

Największą korzyścią jest to, że nie są wymagane do „hack” urls.py, aby uwzględnić wszystkie rodzaje argumentów kontekstowych, można wykorzystać wszystkie funkcje dostępne w widokach opartych na klasach, a jednocześnie udostępniać niestandardowe treści kontekstowe.

+0

Czy to nie jest dokładnie akceptowana odpowiedź? – fariza

+0

@fariza - Kod jest taki sam, różnica polega na podejściu. Zaakceptowana odpowiedź używa powyższego kodu do przekazania danych do 'as_view' (jeśli dobrze rozumiem). Sugeruje to użycie kodu do przekazania argumentów bezpośrednio do szablonu, bez konieczności modyfikowania czegokolwiek w 'urls.py'. – eykanal

+0

pierwotne pytanie dotyczyło usunięcia funkcji i sposobu jej przywrócenia. Ta funkcja oznacza ogólne widoki, które akceptują dodatkowy kontekst z pliku urls.py – fariza

Powiązane problemy