Django基于类的视图:如何将其他参数传递给as_view方法?

Rud*_*lah 88 python django django-views django-generic-views

我有一个基于类的自定义视图

# 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)
Run Code Online (Sandbox Code Playgroud)

我想像这样传入slug参数(或其他参数到视图)

MyView.as_view(slug='hello_world')
Run Code Online (Sandbox Code Playgroud)

我是否需要覆盖任何方法才能执行此操作?

Dan*_*son 108

如果你的urlconf看起来像这样:

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

然后slug将在你的视图函数(例如'get_queryset')中可用,如下所示:

self.kwargs['slug']
Run Code Online (Sandbox Code Playgroud)

  • 如果这是一个可选参数,为了避免异常:使用`self.kwargs.get('slug',None)` (17认同)
  • 只是好奇,这个"self.kwargs"何时/何地填充?我正在寻找设置它的基类函数. (6认同)

Rud*_*lah 85

传递给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)
Run Code Online (Sandbox Code Playgroud)

这应该是MyView.as_view(slug='hello_world')有效的.

如果您通过关键字传递变量,请使用Erikkson先生建议的内容:https://stackoverflow.com/a/11494666/9903

  • 永远不要做`import *`。编辑了您的帖子。 (3认同)

Fus*_*ush 18

值得注意的是,您不需要覆盖get_object()以便根据作为关键字arg传递的slug查找对象 - 您可以使用https://docs.djangoproject.com/en/1.5/ref/的属性SingleObjectMixin 基于类的的视图/混入单对象/#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 }}
Run Code Online (Sandbox Code Playgroud)

(都slug_fieldslug_url_kwarg默认'slug')


Ale*_*raf 13

如果要将对象get_context_data添加到模板的上下文中,可以覆盖并添加到其上下文.如果您需要request.user,请求也是self的一部分.

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
Run Code Online (Sandbox Code Playgroud)


Yar*_*nko 10

您可以从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'),
Run Code Online (Sandbox Code Playgroud)

在这种情况下,传递给视图的参数不一定是View类的实例变量.使用此方法,您无需将默认页面名称硬编码到YourView模型中,但您可以将其作为urlconf中的参数传递.


Emi*_*ron 7

正如Yaroslav Nikitenko所述,如果您不想将新的实例变量硬编码到View类,您可以传递额外的选项来查看函数,urls.py如下所示:

url(r'^$', YourView.as_view(), {'slug': 'hello_world'}, name='page_name')
Run Code Online (Sandbox Code Playgroud)

我只是想在视图中添加如何使用它.您可以实现以下方法之一:

# 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
Run Code Online (Sandbox Code Playgroud)