2013-04-02 14 views
55

Non mi è chiaro come sia meglio accedere ai parametri URL nelle viste basate sulla classe in Django 1.5.Parametri URL e logica nelle viste basate sulla classe Django (TemplateView)

Si consideri il seguente:

Vista:

from django.views.generic.base import TemplateView 


class Yearly(TemplateView): 
    template_name = "calendars/yearly.html" 

    current_year = datetime.datetime.now().year 
    current_month = datetime.datetime.now().month 

    def get_context_data(self, **kwargs): 
     context = super(Yearly, self).get_context_data(**kwargs) 
     context['current_year'] = self.current_year 
     context['current_month'] = self.current_month 
     return context 

URLCONF:

from .views import Yearly 


urlpatterns = patterns('', 
    url(
     regex=r'^(?P<year>\d+)/$', 
     view=Yearly.as_view(), 
     name='yearly-view' 
    ), 
) 

voglio accedere al parametro year a mio avviso, in modo da poter fare la logica del tipo:

Come si può meglio accedere al parametro url in CBV come sopra, che è sottoclasse di TemplateView e dove si dovrebbe posizionare idealmente la logica come questa, ad es. in un metodo?

risposta

71

Per accedere ai parametri URL nelle viste a base di classe, utilizzare self.args o self.kwargs in modo che avrebbe accedervi facendo self.kwargs['year']

+1

È correttamente inteso che non dovrei creare variabili direttamente nella vista come ho sopra? (qualcosa su di loro è persistente).Inoltre non capisco dove dovrei posizionare la logica come sopra, ad es. in quale metodo? Anche quando faccio 'year = self.kwargs ['year']' nella vista ottengo 'NameError: self not defined'. –

+2

Tecnicamente non dovresti dal momento che sono a livello di classe e sono variabili di classe. Per quanto riguarda 'NameError', dove stai provando a fare' year = self.kwargs ['year'] '? Dovresti farlo con un metodo, non puoi farlo a livello di classe. Quindi, per esempio, stai usando un 'TemplateView', il che significa che dovresti fare la logica nel tuo override' get_context_data'. – Ngenator

+2

Solo per referenziazione: la documentazione su self.request, self.args etc è disponibile in https://docs.djangoproject.com/en/1.10/topics/class-based-views/generic-display/ – LShi

7

Finora sono stato solo in grado di accedere a questi parametri URL all'interno del metodo di get_queryset, anche se L'ho provato solo con un ListView e non con un TemplateView. Userò il parametro URL per creare un attributo l'istanza dell'oggetto, quindi utilizzare tale attributo get_context_data per popolare il contesto:

class Yearly(TemplateView): 
    template_name = "calendars/yearly.html" 

    current_year = datetime.datetime.now().year 
    current_month = datetime.datetime.now().month 

    def get_queryset(self): 
     self.year = self.kwargs['year'] 
     queryset = super(Yearly, self).get_queryset() 
     return queryset 

    def get_context_data(self, **kwargs): 
     context = super(Yearly, self).get_context_data(**kwargs) 
     context['current_year'] = self.current_year 
     context['current_month'] = self.current_month 
     context['year'] = self.year 
     return context 
+0

Trovo che strano, c'è un errore o qualcosa quando provi a fare 'context ['year'] = self.kwargs ['year']'? Dovrebbe essere accessibile ovunque nella classe. – Ngenator

+0

@Ngenator: ho appena creato un progetto django pulito per ricontrollare e risulta che sei corretto. Non sono sicuro di cosa stia impedendo questo nel mio codice originale, ma lo scoprirò :). Grazie per l'heads-up – hellsgate

37

Nel caso in cui si passa parametro URL simile a questo:

http://<my_url>/?order_by=created 

è possibile accedere in visualizzazione basata classe utilizzando self.request.GET (la sua non è presentato in self.argsself.kwargs):

class MyClassBasedView(ObjectList): 
    ... 
    def get_queryset(self): 
     order_by = self.request.GET.get('order_by') or '-created' 
     qs = super(MyClassBasedView, self).get_queryset() 
     return qs.order_by(order_by) 
+2

Grazie! Questo mi ha confuso ... Continuo a leggere cose che implicano che i parametri HTTP saranno nei kwarg. – foobarbecue

+0

Puoi mostrare get_queryset() della superclasse di MyClassBasedView? Vorrei solo 'qs = .oggetti. ' – Timo

15

ho trovato questo soluzione elegante, e per Django 1.5 o superiore, come ha sottolineato here:

Django’s generic class based views now automatically include a view variable in the context. This variable points at your view object.

Nel vostro views.py:

from django.views.generic.base import TemplateView  

class Yearly(TemplateView): 
    template_name = "calendars/yearly.html" 
    # No here 
    current_year = datetime.datetime.now().year 
    current_month = datetime.datetime.now().month 

    # dispatch is called when the class instance loads 
    def dispatch(self, request, *args, **kwargs): 
     self.year = kwargs.get('year', "any_default") 

    # other code 

La soluzione spedizione trovato in questo question.
Poiché view è già passato nel contesto del modello, non è necessario preoccuparsene. Nel vostro yearly.html file di modello, è possibile accedere a tali visualizzare gli attributi semplicemente:

{{ view.year }} 
{{ view.current_year }} 
{{ view.current_month }} 

È possibile mantenere il vostro urlconf così com'è.

bene ricordare che ottenere informazioni nel contesto del modello sovrascrive l'get_context_data(), in modo che sia in qualche modo rompendo azione di fagioli flusso di Django.

Problemi correlati