【问题标题】:Django class-based view: How do I pass additional parameters to the as_view method?Django 基于类的视图:如何将附加参数传递给 as_view 方法?
【发布时间】:2012-07-14 17:17:51
【问题描述】:

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

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

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

【问题讨论】:

    标签: python django django-views django-generic-views


    【解决方案1】:

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

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

    那么 slug 将在您的视图函数(例如“get_queryset”)中可用,如下所示:

    self.kwargs['slug']
    

    【讨论】:

    • 为了避免在这是可选参数的情况下出现异常:使用self.kwargs.get('slug', None)
    • 只是好奇,这个“self.kwargs”是什么时候/在哪里填充的?我正在寻找设置它的基类函数。
    • github.com/django/django/blob/master/django/views/generic/…class View: def as_view(cls, **initkwargs): def view(request, *args, **kwargs):
    • 不回答问题。
    • 此方法现已弃用,现在您可以使用url('&lt;slug:slug&gt;', MyView.as_view(), name='my_named_view')
    【解决方案2】:

    传递给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

    【讨论】:

    • 永远不要import *。编辑了您的帖子。
    • @holms 为了启发未来的读者,PEP8 说“应该避免通配符导入(来自 import )”。应该没有必须的那么强大,这是一个例子,但绝对是 *应该避免通配符导入:python.org/dev/peps/pep-0008/#imports
    • 没有什么是必须的,我们可以以任何我们想要的方式破坏我们想要的任何东西,但是 pep8 只是实践的推荐,在 python 社区中,将所有这些实践用作尽可能避免进一步的问题。当我提交代码时,我的 linter 总是空的 :) 无论如何。
    • slug='hello_world' 对于实际变量的值是多少?
    • 我猜 slug 是一个类变量而不是一个实例变量。
    【解决方案3】:

    值得注意的是,您无需重写 get_object() 即可根据作为关键字 arg 传递的 slug 查找对象 - 您可以使用 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 }}
    

    slug_fieldslug_url_kwarg 默认为 'slug'

    【讨论】:

    • 我是否应该将我的答案转换为 wiki 答案并将您的代码添加到其中?
    【解决方案4】:

    如果您想将对象添加到模板的上下文中,您可以覆盖 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
    

    【讨论】:

    • MyObject 是什么?
    【解决方案5】:

    你可以从 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'),
    

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

    【讨论】:

    【解决方案6】:

    Yaroslav Nikitenko 所述,如果您不想将新的实例变量硬编码到 View 类中,您可以像这样从urls.py 中的pass extra options to view functions

    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
    

    【讨论】:

    • 我想在Yaroslav Nikitenko的回答中编辑这个,但被拒绝了,所以我自己做了,因为我觉得这是我需要的时候缺少的信息。
    • @YaroslavNikitenko 事后看来,它太大了,无法编辑,最好以新答案的形式回复。
    • @EmileBergeron 最初的问题是关于通用视图,例如DetailView 类。你能解释一下如何在那里使用它吗?
    • 有没有办法让这些额外的参数可用于基于类的视图中的所有 HTTP 方法?现在我正在做get(self, request, model: Model): passput(self, request, model: Model): pass 等。如果我可以在一个地方分配和输入“模型”,那就更整洁了。
    • @kiloton 如果搜索文档和 Stack Overflow 没有解决您的问题,您应该提出一个新问题。
    【解决方案7】:

    对于 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'),
    ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-21
      相关资源
      最近更新 更多