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 2015年

github.com/django/django/blob/master/django/views/generic/...class View: def as_view(cls, **initkwargs): def view(request, *args, **kwargs):
アポロデータ

質問に答えません。
Kireeti K 2018

このメソッドは廃止され、使用できるようになりましたurl('<slug:slug>', MyView.as_view(), name='my_named_view')
Rahat Zaman

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')うまくいくはずです。

キーワードを介して変数を渡す場合は、Erikkson氏の提案を使用してくださいhttps ://stackoverflow.com/a/11494666/9903


2
絶対にしないでくださいimport *。投稿を編集しました。
ホルム

@holmsは将来の読者の啓蒙のために、「(<module> importからの)ワイルドカードのインポートは避けるべきである」と述べています。shouldは必要以上に強くなく、これは例ですが、はい*ワイルドカードインポートは避けてくださいpython.org/dev/peps/pep-0008/#imports

どこでも必要なものは何もありません。好きなように好きなように壊すことができますが、pep8はプラクティスの推奨にすぎません。Pythonコミュニティでは、さらなる問題を回避するために、これらのプラクティスを可能な限り使用することが経験則です。私のコードをコミットするとき、私のリンターは常に空です:)何があっても。
ホルム

実際の変数のslug = 'hello_world'の値は何ですか?
ゴンザロダンブラ

19

get_object()キーワード引数として渡されたスラッグに基づいてオブジェクトを検索するためにオーバーライドする必要がないことに注意する必要があります-https://docs.djangoproject.com/en/1.5/ref/の属性を使用できSingleObjectMixin ます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_fieldslug_url_kwargデフォルトへ'slug'


1
私の回答をWikiの回答にして、それにコードを追加する必要がありますか?

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

なにMyObject
Rob Kwasowski、

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からパラメーターとして渡すだけで済みます。


ありがとう、これをかなり探していました!
2017年

7

で述べたようにヤロスラフNikitenkoあなたは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
ヤロスラフ・ニキテンコさんの回答でこれを編集したかったのですが、却下されたので、必要な時に欠けていた情報だと思って自作しました。
Emile Bergeron、2016

投稿ありがとうございます!それがあなたの編集を拒否したのが私だったかどうか、またその理由は覚えていません。
Yaroslav Nikitenko 2017年

@YaroslavNikitenko後から考えると、編集するには大きすぎて、新しい答えの形での返信としては最高でした。
エミールベルジェロン2017年

@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'),
]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.