Класс Django: как передать дополнительные параметры методу as_view?
У меня есть пользовательский вид на основе класса
# myapp/views.py
from django.views.generic import *
class MyView(DetailView):
template_name = 'detail.html'
model = MyModel
def get_object(self, queryset=None):
return queryset.get(slug=self.slug)
Я хочу передать в параметр slug (или другие параметры для представления), как этот
MyView.as_view(slug='hello_world')
Нужно ли переопределять любые методы, чтобы это сделать?
Ответы
Ответ 1
Каждый параметр, переданный методу as_view
, является переменной экземпляра класса View. Это означает добавить slug
в качестве параметра, который вы должны создать в качестве переменной экземпляра в своем подклассе:
# myapp/views.py
from django.views.generic import *
class MyView(DetailView):
template_name = 'detail.html'
model = MyModel
# additional parameters
slug = None
def get_object(self, queryset=None):
return queryset.get(slug=self.slug)
Это должно сделать работу MyView.as_view(slug='hello_world')
.
Если вы передаете переменные через ключевые слова, используйте то, что предложил г-н Эрикссон: fooobar.com/questions/82789/...
Ответ 2
Если ваш urlconf выглядит примерно так:
url(r'^(?P<slug>[a-zA-Z0-9-]+)/$', MyView.as_view(), name = 'my_named_view')
тогда slug будет доступен внутри ваших функций просмотра (например, 'get_queryset') следующим образом:
self.kwargs['slug']
Ответ 3
Стоит отметить, что вам не нужно переопределять get_object()
, чтобы искать объект на основе slug, переданного как ключевое слово arg, - вы можете использовать атрибуты SingleObjectMixin
https://docs.djangoproject.com/en/1.5/ref/class-based-views/mixins-single-object/#singleobjectmixin
# views.py
class MyView(DetailView):
model = MyModel
slug_field = 'slug_field_name'
slug_url_kwarg = 'model_slug'
context_object_name = 'my_model'
# urls.py
url(r'^(?P<model_slug>[\w-]+)/$', MyView.as_view(), name = 'my_named_view')
# mymodel_detail.html
{{ my_model.slug_field_name }}
(как slug_field
, так и slug_url_kwarg
по умолчанию 'slug'
)
Ответ 4
Если вы хотите добавить объект в контекст для шаблона, вы можете переопределить get_context_data
и добавить его в контекст. Запрос также является частью "я", если вам нужен request.user.
def get_context_data(self, **kwargs):
context = super(MyTemplateView, self).get_context_data(**kwargs)
if 'slug' in self.kwargs:
context['object'] = get_object_or_404(MyObject, slug=self.kwargs['slug'])
context['objects'] = get_objects_by_user(self.request.user)
return context
Ответ 5
Вы можете передавать параметры из urls.py
https://docs.djangoproject.com/en/1.7/topics/http/urls/#passing-extra-options-to-view-functions
Это также работает для общих представлений. Пример:
url(r'^$', views.SectionView.as_view(), { 'pk': 'homepage', 'another_param':'?'}, name='main_page'),
В этом случае параметры, переданные в представление, не обязательно должны быть переменными экземпляра класса View. Используя этот метод, вам не нужно жестко указывать имя страницы по умолчанию в модели YourView, но вы можете просто передать ее как параметр из urlconf.
Ответ 6
Как указано Ярослав Никитенко, если вы не хотите жестко кодировать новую переменную экземпляра класса View, вы можете передать дополнительные опции для просмотра функций от urls.py
следующим образом:
url(r'^$', YourView.as_view(), {'slug': 'hello_world'}, name='page_name')
Я просто хотел добавить, как использовать его из представления. Вы можете реализовать один из следующих способов:
# If slug is optional
def the_function(self, request, slug=None):
# use slug here
# if slug is an optional param among others
def the_function(self, request, **kwargs):
slug = kwargs.get("slug", None)
other_param = kwargs.get("other_param", None)
# If slug is required
def the_function(self, request, slug):
# use slug here