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

我是否需要重写任何方法才能做到这一点?

Answers:


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

6
只是好奇,这个“ self.kwargs”何时/何地填充?我正在寻找设置此位置的基类函数。
binithb

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 '18

现在已弃用此方法,现在可以使用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为将来的读者提供启迪,PEP8表示“ 应避免通配符导入(来自<module> import )”。应该没有那么强,这是一个例子,但是可以肯定*应该避免通配符导入:python.org/dev/peps/pep-0008/#imports

在任何地方都没有什么是必须的,我们可以用任何方式破坏我们想要的任何东西,但是pep8只是实践的建议,在python社区中,尽可能多地使用所有这些实践以避免进一步的问题是一条经验法则。提交代码时,我的linter总是空的:)不管怎样。
霍尔姆斯

实际变量的slug ='hello_world'的值是多少?
贡萨洛·丹布拉

19

值得注意的是,您不需要重写get_object()即可基于作为关键字arg传递的段来查找对象-您可以使用SingleObjectMixin https://docs.djangoproject.com/en/1.5/ref/基于类的视图/ mixins-单个对象/#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
罗布·夸索夫斯基

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中传递即可。


谢谢,我为此花了很长时间!
Ilja

7

Yaroslav 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
我想在Yaroslav Nikitenko的答案中对此进行编辑,但是它被拒绝了,所以我做了我自己的,因为我觉得它是我需要时所缺少的信息。
Emile Bergeron

谢谢你的文章!我不记得是不是我拒绝了您的编辑,为什么。
雅罗斯拉夫·尼基琴科

@YaroslavNikitenko事后看来,它太大了,无法编辑,最好以新答案的形式答复。
Emile Bergeron

@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'),
]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.