【问题标题】:Django - passing an attribute value to as_view in TemplateViewDjango - 将属性值传递给 TemplateView 中的 as_view
【发布时间】:2014-06-16 12:54:25
【问题描述】:

这是我的观点(简化):

class MyView(TemplateView):
    def __init__(self):
        self.foo = 'bar'
        super(MyView, self).__init__()

这是在 urls.py 中:

url(
    r'^/foo/$',
    MyView.as_view(foo='baz'), name='my_view'
)

当我运行它时,我收到以下错误:

TypeError: MyView() received an invalid keyword 'foo'. as_view only accepts arguments that are already attributes of the class.

为什么?我认为这行得通。 :/

至少根据这篇文章: http://reinout.vanrees.org/weblog/2011/08/24/class-based-views-walkthrough.html#class-view

如果我理解正确,这应该将属性foo 设置为'baz' 传入as_view 的值。如果as_view 中没有任何属性,则值应为'bar',如__init__ 中定义的那样。

【问题讨论】:

    标签: python django django-templates


    【解决方案1】:

    您正在为__init__() 中的类的实例显式设置一个值。然而,类本身仍然没有属性foo,因为它不知道实例上的动态属性:hasattr(MyView, 'foo') 总是返回False

    这将像您预期的那样工作:

    class MyView(TemplateView):
        foo = 'bar'
    
    url(
        r'^/foo/$',
        MyView.as_view(foo='baz'), name='my_view'
    )
    

    【讨论】:

    • 这是否会仅针对该视图实例或类本身更改此值?如果我在 urls.py 中有另一个没有参数的 URL 绑定并且在问题之后调用它会发生什么?里面的值是'bar' 还是'baz'
    • @morgoth84 MyView 类将使用传递给as_view 方法的关键字参数进行实例化。它不会改变类本身的任何属性。如果另一个 url 绑定没有为foo 传递另一个值,则MyView 实例上的值将是默认的'bar'
    • @morgoth84 还有一件事,您可以在View 子类上覆盖__init__,但您必须捕获所有关键字参数(__init__(self, **kwargs))并将它们传递给对super 的调用,否则你会弄坏东西。
    【解决方案2】:

    Django View 类的源代码有这个:

    if not hasattr(cls, key):
        raise TypeError
    

    因此,仅在 __init__ 中的实例上创建 attr 是不够的……它必须存在于类本身上:

    class MyView(TemplateView):
        foo = 'bar'
    

    【讨论】:

    • Django 在 View 上的默认实现 __init__ 将处理所有关键字参数并在实例上设置它们。如果您尝试传递另一个关键字参数,您对__init__ 的实现实际上会破坏事情。
    猜你喜欢
    • 2023-03-03
    • 1970-01-01
    • 2021-02-03
    • 1970-01-01
    • 2014-05-21
    • 1970-01-01
    • 2017-11-23
    • 2013-01-30
    • 1970-01-01
    相关资源
    最近更新 更多