Подтвердить что ты не робот

URL-параметры и логика в представлении класса Django (TemplateView)

Мне неясно, как лучше всего получить доступ к URL-параметрам в представлениях на основе классов в Django 1.5.

Учтите следующее:

Посмотреть:

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

привязок:

from .views import Yearly


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

Я хочу получить доступ к параметру year на мой взгляд, чтобы я мог сделать логику, например:

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

Как лучше всего получить доступ к параметру url в CBV, как указано выше, который находится в подклассе TemplateView и где в идеале следует разместить логику, например, так: в методе?

4b9b3361

Ответ 1

Чтобы получить доступ к параметрам url в представлениях на основе классов, используйте self.args или self.kwargs, чтобы вы могли получить к нему доступ, выполнив self.kwargs['year']

Ответ 2

Если вы пропустите параметр URL, например:

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

Вы можете получить доступ к нему в представлении на основе класса с помощью self.request.GET (его не указано в self.args и не в 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)

Ответ 3

Я нашел это элегантное решение, и для django 1.5 или выше, как указано здесь:

Общие представления на основе классов Djangos теперь автоматически включают представление переменная в контексте. Эта переменная указывает на ваш объект просмотра.

В ваших 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)

Решение по отправке найдено в этом вопросе.
Поскольку представление уже передано в контексте шаблона, вам не нужно беспокоиться об этом. В файле шаблона year.html можно получить доступ к этим атрибутам представления просто:

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

Вы можете сохранить свой urlconf как есть.

Стоит отметить, что получение информации в контекст вашего шаблона перезаписывает get_context_data(), поэтому это как-то нарушает поток bean-компонента действия django.

Ответ 4

До сих пор мне удалось получить доступ к этим параметрам url из метода get_queryset, хотя я только пробовал его с помощью ListView, а не с TemplateView. Я буду использовать параметр url для создания атрибута на экземпляре объекта, а затем использовать этот атрибут в get_context_data для заполнения контекста:

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

Ответ 5

Как насчет использования декораторов Python, чтобы сделать это понятным:

class Yearly(TemplateView):

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