121 votes

Paramètres URL et logique dans les vues Django basées sur des classes (TemplateView)

Je ne vois pas très bien comment accéder aux paramètres d'URL dans les vues basées sur les classes dans Django 1.5.

Considérez ce qui suit :

Voir :

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'
    ),
)

Je veux accéder à la year dans ma vue, donc je peux faire une logique comme :

month_names = [
    "January", "February", "March", "April", 
    "May", "June", "July", "August", 
    "September", "October", "November", "December"
]

for month, month_name in enumerate(month_names, start=1):
    is_current = False
    if year == current_year and month == current_month:
        is_current = True
        months.append({
            'month': month,
            'name': month_name,
            'is_current': is_current
        })

Comment accéder au mieux au paramètre url dans des CBVs comme celui ci-dessus qui est sous-classé de TemplateView et où doit-on idéalement placer la logique de ce type, par exemple dans une méthode ?

150voto

Ngenator Points 7685

Pour accéder aux paramètres url dans les vues basées sur les classes, utilisez self.args o self.kwargs Vous pouvez donc y accéder en faisant self.kwargs['year']

82voto

niekas Points 1228

Dans le cas où vous passez le paramètre URL comme ceci :

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

Vous pouvez y accéder dans la vue basée sur la classe en utilisant self.request.GET (elle n'est pas présentée dans self.args ni dans self.kwargs ):

from django.views.generic.list import ListView

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

28voto

Evhz Points 3279

J'ai trouvé cette solution élégante, et pour django 1.5 ou plus, comme indiqué aquí :

Les vues génériques de Django basées sur des classes incluent maintenant automatiquement une variable de vue dans le contexte. Cette variable pointe vers votre objet de vue.

Dans votre views.py :

from django.views.generic.base import TemplateView    

class Yearly(TemplateView):
    template_name = "calendars/yearly.html"
    # Not 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

    # needed to have an HttpResponse
    return super(Yearly, self).dispatch(request, *args, **kwargs)

La solution de répartition trouvée dans ce question .
Comme le voir est déjà passé dans le contexte de Template, vous n'avez pas vraiment besoin de vous en préoccuper. Dans votre fichier template yearly.html, il est possible d'accéder à ces attributs de vue simplement par :

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

Vous pouvez conservez votre urlconf tel qu'il est.

Il est utile de mentionner que l'obtention d'informations dans le contexte de votre modèle écrase la fonction get_context_data(), ce qui rompt d'une certaine manière l'interface de django. haricot magique flux.

15voto

danizen Points 51

Pourquoi ne pas simplement utiliser les décorateurs Python pour rendre cela intelligible :

class Yearly(TemplateView):

    @property
    def year(self):
       return self.kwargs['year']

8voto

hellsgate Points 1869

Jusqu'à présent, je n'ai pu accéder à ces paramètres url qu'à partir de la méthode get_queryset, bien que je n'aie essayé qu'avec une ListView et non une TemplateView. Je vais utiliser le paramètre url pour créer un attribut sur l'instance de l'objet, puis utiliser cet attribut dans get_context_data pour remplir le contexte :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X