#python #django #django-templates
#python #django #django-шаблоны
Вопрос:
Это мой взгляд (упрощенный):
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__
.
Ответ №1:
Вы явно устанавливаете значение для экземпляра класса в __init__()
. Однако сам класс по-прежнему не имеет атрибута foo
, поскольку он не знает о динамических атрибутах в экземплярах: hasattr(MyView, 'foo')
всегда возвращает False
.
Это будет работать так, как вы ожидали, что ваш код будет работать:
class MyView(TemplateView):
foo = 'bar'
url(
r'^/foo/$',
MyView.as_view(foo='baz'), name='my_view'
)
Комментарии:
1. Изменит ли это это значение только для этого экземпляра представления или для самого класса? Что произойдет, если у меня есть другая привязка URL без параметра в urls.py и это называется в честь этого вопроса из вопроса? Будет ли значение внутри
'bar'
или'baz'
?2. @morgoth84
MyView
Класс будет создан с использованием аргументов ключевого слова, переданныхas_view
методу. Это не изменит ни одного атрибута в самом классе. Если другая привязка url не передает другое значение дляfoo
, значение дляMyView
экземпляра будет по умолчанию'bar'
.3. @morgoth84 Еще одна вещь, вы можете переопределить
__init__
View
подклассы, но вам нужно захватить все аргументы ключевого слова (__init__(self, **kwargs)
) и передать их вызовуsuper
, иначе вы сломаете материал.
Ответ №2:
Исходный код View
класса Django имеет это, хотя:
if not hasattr(cls, key):
raise TypeError
Таким образом, недостаточно создать attr для экземпляра в __init__
… он должен существовать в самом классе:
class MyView(TemplateView):
foo = 'bar'
Комментарии:
1. Реализация
__init__
on в Django по умолчаниюView
будет обрабатывать все аргументы ключевого слова и устанавливать их в экземпляре. Ваша реализация__init__
фактически нарушит работу, если вы попытаетесь передать другой аргумент ключевого слова.