Ответ 1
Чтобы получить доступ к параметрам url в представлениях на основе классов, используйте self.args
или self.kwargs
, чтобы вы могли получить к нему доступ, выполнив self.kwargs['year']
Мне неясно, как лучше всего получить доступ к 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
и где в идеале следует разместить логику, например, так: в методе?
Чтобы получить доступ к параметрам url в представлениях на основе классов, используйте self.args
или self.kwargs
, чтобы вы могли получить к нему доступ, выполнив self.kwargs['year']
Если вы пропустите параметр 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)
Я нашел это элегантное решение, и для 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.
До сих пор мне удалось получить доступ к этим параметрам 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
Как насчет использования декораторов Python, чтобы сделать это понятным:
class Yearly(TemplateView):
@property
def year(self):
return self.kwargs['year']