Django sınıf tabanlı görünüm: Ek parametreleri as_view yöntemine nasıl aktarırım?


97

Özel bir sınıfa dayalı görünümüm var

# 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 parametresini (veya diğer parametreleri görünüme) bunun gibi geçirmek istiyorum

MyView.as_view(slug='hello_world')

Bunu yapabilmek için herhangi bir yöntemi geçersiz kılmam gerekir mi?

Yanıtlar:


114

Urlconf'unuz şuna benziyorsa:

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

daha sonra bilgi, şu şekilde görünüm işlevlerinizde ('get_queryset' gibi) kullanılabilir olacaktır:

self.kwargs['slug']

18
Bunun isteğe bağlı bir parametre olması durumunda bir istisnadan kaçınmak için: kullanınself.kwargs.get('slug', None)
Risadinha

6
Merak ediyorum, bu "self.kwargs" ne zaman / nerede dolduruluyor? Bunun ayarlandığı temel sınıf işlevini arıyorum.
binithb

In github.com/django/django/blob/master/django/views/generic/... içindeclass View: def as_view(cls, **initkwargs): def view(request, *args, **kwargs):
Apollo Verileri

Soruyu cevaplamıyorum.
Kireeti K

Bu yöntem artık kullanımdan kaldırıldı, artık kullanabilirsinizurl('<slug:slug>', MyView.as_view(), name='my_named_view')
Rahat Zaman

92

as_viewYönteme iletilen her parametre , View sınıfının bir örnek değişkenidir. Bu, slugparametre olarak eklemek anlamına gelir, onu alt sınıfınızda bir örnek değişkeni olarak oluşturmanız gerekir:

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

Bu MyView.as_view(slug='hello_world')işe yaramalı.

Değişkenleri anahtar kelimeler üzerinden geçiriyorsanız, Bay Erikkson'un önerdiği şeyi kullanın: https://stackoverflow.com/a/11494666/9903


3
Asla yapmayın import *. Yayınınızı düzenlediniz.
Holms

@holms gelecekteki okuyucuların aydınlanması için, PEP8 "Wildcard içe aktarmalarından (<modül> içe aktarımından ) kaçınılmalıdır" diyor. Olması gerektiği kadar güçlü olmamalı ve bu bir örnek ama evet kesinlikle * joker karakter içe aktarmalardan

Hiçbir şey hiçbir yerde zorunlu değildir, istediğimiz herhangi bir şekilde istediğimiz her şeyi kırabiliriz, ancak pep8 sadece uygulamaların bir tavsiyesidir ve python topluluğunda daha fazla problemden kaçınmak için tüm bu uygulamaları mümkün olduğunca kullanmak temel bir kuraldır. Kodumu işlediğimde linterim her zaman boştur :) ne olursa olsun.
Holms

Gerçek bir değişken için slug = 'hello_world' değeri nedir?
Gonzalo Dambra

19

get_object()Anahtar kelime argümanı olarak iletilen bir sümüklüböceğe dayalı bir nesneyi aramak için geçersiz kılmanıza gerek olmadığını belirtmekte fayda var - https://docs.djangoproject.com/en/1.5/ref/ özniteliklerini kullanabilirsiniz. SingleObjectMixin sınıf tabanlı görünümler / mixins-tek nesne / # 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 }}

(hem slug_fieldve slug_url_kwargvarsayılan olarak 'slug')


1
Cevabımı bir wiki cevabına dönüştürmeli ve kodunuzu buna eklemeli miyim?

15

Şablonun bağlamına bir nesne eklemek istiyorsanız, onu geçersiz kılabilir get_context_datave içeriğine ekleyebilirsiniz. İsteği de bir parçasıdır öz İhtiyacınız halinde 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

Nedir MyObject?
Rob Kwasowski

13

Parametreleri urls.py https://docs.djangoproject.com/en/1.7/topics/http/urls/#passing-extra-options-to-view-functions adresinden aktarabilirsiniz.

Bu aynı zamanda genel görünümler için de geçerlidir. Misal:

url(r'^$', views.SectionView.as_view(), { 'pk': 'homepage', 'another_param':'?'}, name='main_page'),

Bu durumda, görünüme iletilen parametrelerin mutlaka View sınıfının örnek değişkenleri olması gerekmez. Bu yöntemi kullanarak, varsayılan sayfa adını YourView modeline sabit kodlamanız gerekmez, ancak bunu urlconf'tan bir parametre olarak geçirebilirsiniz.


7

Tarafından belirtildiği gibi Yaroslav Nikitenko Görünüm sınıfına yeni bir örnek değişkenini kodlamalısınız istemiyorsanız, şunları yapabilirsiniz işlevleri görüntülemek için ekstra seçenekler geçmesi gelen urls.pyböyle:

url(r'^$', YourView.as_view(), {'slug': 'hello_world'}, name='page_name')

Görünümden nasıl kullanılacağını eklemek istedim. Aşağıdaki yöntemlerden birini uygulayabilirsiniz:

# 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
Bunu Yaroslav Nikitenko'nun cevabında düzenlemek istedim , ancak reddedildi, bu yüzden kendim yaptım çünkü ihtiyacım olduğunda eksik bilgi olduğunu hissettim.
Emile Bergeron

@YaroslavNikitenko Geriye dönüp baktığımızda, bir düzenleme için çok büyüktü ve en iyisi yeni bir cevap şeklinde bir cevaptı.
Emile Bergeron

@EmileBergeron İlk soru DetailViewsınıf gibi genel görüşler hakkındaydı . Orada nasıl kullanılacağını açıklayabilir misin?
bartaelterman

3

Django 3.0 için bu benim için çalıştı:

# 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'),
]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.