web-dev-qa-db-fra.com

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

Il n’est pas clair pour moi comment il est préférable d’accéder aux paramètres d’URL dans les vues basées sur les classes dans Django 1.5.

Considérer 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

RLCONF:

from .views import Yearly


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

Je souhaite accéder au paramètre year de mon point de vue afin de pouvoir utiliser une logique telle que:

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 les CBV, comme ci-dessus, qui est sous-classé de TemplateView, et où placer idéalement la logique comme celle-ci, par exemple. dans une méthode?

83
user1319936

Pour accéder aux paramètres d'URL dans les vues basées sur les classes, utilisez self.args ou self.kwargs afin que vous y accédiez en faisant self.kwargs['year']

98
Ngenator

Si vous passez le paramètre d'URL comme ceci:

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

Vous pouvez y accéder dans la vue basée sur les classes en utilisant self.request.GET _ (il n'est pas présenté dans self.args ni dans self.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)
48
niekas

J'ai trouvé cette solution élégante, et pour Django 1,5 ou plus, comme indiqué ici :

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

Dans votre view.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

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

La solution d'expédition trouvée dans cette question .
Comme vue est déjà passé dans le contexte Template, vous n'avez pas vraiment besoin de vous en soucier. Dans votre fichier de modèle annual.html, il est possible d'accéder à ces attributs de vue simplement par:

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

Vous pouvez conserver votre urlconf tel quel.

Il est bon de mentionner que le fait d’obtenir des informations dans le contexte de votre modèle écrase la méthode get_context_data (); elle interrompt donc le flux de Django action bean.

20
Evhz

Jusqu'à présent, je n'ai pu accéder à ces paramètres d'URL qu'à partir de la méthode get_queryset, bien que je ne l'ais essayé qu'avec un ListView et non un TemplateView. Je vais utiliser le paramètre url pour créer un attribut sur l'instance d'objet, puis utiliser cet attribut dans get_context_data pour renseigner 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
8
hellsgate

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

class Yearly(TemplateView):

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