Tampilan berbasis kelas Django: Bagaimana saya meneruskan parameter tambahan ke metode as_view?

95

Saya memiliki tampilan berbasis kelas kustom

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

Saya ingin meneruskan parameter slug (atau parameter lain ke tampilan) seperti ini

MyView.as_view(slug='hello_world')

Apakah saya perlu mengganti metode apa pun untuk dapat melakukan ini?

Serjik
sumber

Jawaban:

113

Jika urlconf Anda terlihat seperti ini:

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

maka slug akan tersedia di dalam fungsi tampilan Anda (seperti 'get_queryset') seperti ini:

self.kwargs['slug']
Daniel Eriksson
sumber
18
Untuk menghindari pengecualian jika ini adalah parameter opsional: gunakanself.kwargs.get('slug', None)
Risadinha
6
Hanya ingin tahu, kapan / di mana "self.kwargs" ini diisi? Saya mencari fungsi kelas dasar di mana ini diatur.
binithb
Di github.com/django/django/blob/master/django/views/generic/… diclass View: def as_view(cls, **initkwargs): def view(request, *args, **kwargs):
Apollo Data
Tidak menjawab pertanyaan itu.
Kireeti K
Metode ini sekarang sudah tidak digunakan lagi, sekarang Anda dapat menggunakanurl('<slug:slug>', MyView.as_view(), name='my_named_view')
Rahat Zaman
91

Setiap parameter yang diteruskan ke as_viewmetode adalah variabel instance dari kelas View. Itu berarti untuk menambahkan slugsebagai parameter Anda harus membuatnya sebagai variabel instan di sub-kelas Anda:

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

Itu seharusnya MyView.as_view(slug='hello_world')berhasil.

Jika Anda meneruskan variabel melalui kata kunci, gunakan saran Tn. Erikkson: https://stackoverflow.com/a/11494666/9903

holms
sumber
2
Tidak pernah import *. Mengedit postingan Anda.
holms
@holms untuk pencerahan bagi pembaca di masa mendatang, PEP8 mengatakan "Impor karakter pengganti (dari impor <module> ) harus dihindari". Seharusnya tidak sekuat keharusan dan ini adalah contoh tetapi ya pasti * harus menghindari impor wildcard: python.org/dev/peps/pep-0008/#imports
Tidak ada keharusan di mana pun, kita dapat merusak apa pun yang kita inginkan dengan cara apa pun yang kita inginkan, tetapi pep8 hanyalah rekomendasi praktik, dan dalam komunitas python, aturan praktis untuk menggunakan semua praktik ini sebanyak mungkin untuk menghindari masalah lebih lanjut. Linter saya selalu kosong ketika saya memasukkan kode saya :) apa pun yang terjadi.
holms
Berapa nilai slug = 'hello_world' untuk variabel sebenarnya?
Gonzalo Dambra
19

Perlu dicatat bahwa Anda tidak perlu menimpa get_object()untuk mencari objek berdasarkan slug yang diteruskan sebagai argumen kata kunci - Anda dapat menggunakan atribut dari 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 }}

(keduanya slug_fielddan slug_url_kwargdefault 'slug')

Fush
sumber
1
haruskah saya mengubah jawaban saya menjadi jawaban wiki dan menambahkan kode Anda ke dalamnya?
15

Jika Anda ingin menambahkan objek ke konteks untuk template, Anda dapat mengganti get_context_datadan menambahkan ke konteksnya. Permintaan juga merupakan bagian dari diri jika Anda membutuhkan 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
Aleck Landgraf
sumber
Apa MyObject?
Rob Kwasowski
13

Anda dapat meneruskan parameter dari urls.py https://docs.djangoproject.com/en/1.7/topics/http/urls/#passing-extra-options-to-view-functions

Ini juga berfungsi untuk tampilan umum. Contoh:

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

Dalam hal ini, parameter yang diteruskan ke tampilan tidak harus berupa variabel instance dari kelas View. Dengan menggunakan metode ini, Anda tidak perlu melakukan hardcode nama halaman default ke dalam model YourView, tetapi Anda bisa meneruskannya sebagai parameter dari urlconf.

Yaroslav Nikitenko
sumber
terima kasih, saya sudah mencari cukup lama untuk ini!
Ilja
7

Seperti yang dinyatakan oleh Yaroslav Nikitenko , jika Anda tidak ingin hardcode variabel contoh baru untuk kelas View, Anda dapat melewati opsi tambahan untuk melihat fungsi dari urls.pyseperti ini:

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

Saya hanya ingin menambahkan cara menggunakannya dari tampilan. Anda dapat menerapkan salah satu metode berikut:

# 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
Emile Bergeron
sumber
1
Saya ingin mengedit ini dalam jawaban Yaroslav Nikitenko , tetapi ditolak, jadi saya membuatnya sendiri karena saya merasa itu adalah informasi yang hilang ketika saya membutuhkannya.
Emile Bergeron
terima kasih atas kiriman Anda! Saya tidak ingat apakah itu saya yang menolak suntingan Anda dan mengapa.
Yaroslav Nikitenko
@YaroslavNikitenko Kalau dipikir-pikir, itu terlalu besar untuk diedit dan paling baik sebagai balasan dalam bentuk jawaban baru.
Emile Bergeron
@EmileBergeron Pertanyaan awal adalah tentang pandangan umum seperti DetailViewkelas. Bisakah Anda menjelaskan cara menggunakannya di sana?
bartaelterman
3

Untuk django 3.0, inilah yang berhasil untuk saya:

# 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'),
]
mizerablebr.dll
sumber