Перегляд на основі класу Django: Як передати додаткові параметри методу as_view?


95

У мене є власний погляд на основі класу

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

Чи потрібно мені замінювати будь-які методи, щоб це зробити?

Відповіді:


113

Якщо ваш urlconf виглядає приблизно так:

url(r'^(?P<slug>[a-zA-Z0-9-]+)/$', MyView.as_view(), name = 'my_named_view')

тоді куля буде доступна всередині ваших функцій перегляду (наприклад, 'get_queryset') таким чином:

self.kwargs['slug']

18
Щоб уникнути винятку, якщо це необов’язковий параметр: використовуйтеself.kwargs.get('slug', None)
Risadinha

6
Просто цікаво, коли / де населений цей "self.kwargs"? Я шукаю функцію базового класу, де це встановлено.
binithb

In github.com/django/django/blob/master/django/views/generic/… вclass View: def as_view(cls, **initkwargs): def view(request, *args, **kwargs):
Apollo Data

Не відповідаючи на запитання.
Kireeti K

Зараз цей метод застарілий, тепер ви можете ним користуватисяurl('<slug:slug>', MyView.as_view(), name='my_named_view')
Рахат Заман

91

Кожен параметр, який передається as_viewметоду, є змінною екземпляра класу View. Це означає, що для додавання slugяк параметра потрібно створити його як змінну примірника у своєму підкласі:

# myapp/views.py
from django.views.generic import DetailView

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')роботу.

Якщо ви передаєте змінні через ключові слова, використовуйте те, що запропонував пан Еріксон: https://stackoverflow.com/a/11494666/9903


2
Ніколи не робіть import *. Відредагував ваш допис.
Холмс

@holms для просвітлення майбутніх читачів, PEP8 зазначає, що " слід уникати імпорту підстановочних символів (із <module> import )". Повинна бути не такою сильною, як повинна, і це приклад, але так, безумовно * слід уникати імпорту підстановочних знаків: python.org/dev/peps/pep-0008/#imports

Ніде нічого не потрібно, ми можемо зламати все, що завгодно, як завгодно, але pep8 - це лише рекомендація практик, а в спільноті python є правилом використовувати всі ці практики якомога більше, щоб уникнути подальших проблем. Мій лінтер завжди порожній, коли я фіксую свій код :), незважаючи ні на що.
Холмс

Яке значення slug = 'hello_world' для фактичної змінної?
Гонсало Дамбра,

19

Варто зазначити, що вам не потрібно перевизначати get_object(), щоб шукати об’єкт на основі кулі, переданої як ключове слово arg - ви можете використовувати атрибути SingleObjectMixin https://docs.djangoproject.com/en/1.5/ref/ погляди на основі класу / 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')


1
чи слід перетворити свою відповідь на відповідь у вікі та додати до неї свій код?

15

Якщо ви хочете додати об’єкт до контексту для шаблону, ви можете замінити 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


13

Ви можете передавати параметри з 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.


дякую, я досить довго шукав це!
Ілля

7

Як заявив Ярослав Нікітенко , якщо ви не хочете , щоб жорстко нову змінну примірника в класі 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

1
Я хотів відредагувати це у відповіді Ярослава Нікітенка , але він був відхилений, тому я зробив свою власну, бо відчував, що це відсутні відомості, коли мені це потрібно.
Еміль Бержерон,

дякую за ваш пост! Я не пам’ятаю, чи це я відхилив вашу редакцію і чому.
Ярослав Нікітенко

@YaroslavNikitenko Оглянувшись назад, це було занадто великим для редагування і найкраще як відповідь у формі нової відповіді.
Еміль Бержерон,

@EmileBergeron Початкове запитання стосувалось загальних поглядів, таких як DetailViewклас. Не могли б ви пояснити, як там використовувати?
bartaelterman

3

Для django 3.0 у мене спрацювало ось що:

# myapp/views.py
from django.views.generic import DetailView

class MyView(DetailView):
    template_name = 'detail.html'
    slug = None

    def get_object(self, queryset=None):
        self.slug = self.kwargs.get('slug', None)
        return queryset.get(slug=self.slug)

# myapp/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('slug/<slug:slug>/', views.MyView.as_view(), name='myview_by_tag'),
]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.