Наследование Django CBV:Переопределение атрибутов
-
14-11-2019 - |
Вопрос
Я создаю собственные представления на основе классов для проекта Django и столкнулся с дизайнерским решением, касающимся атрибутов.
Геттерные функции
Я посмотрел на общие представления Django и увидел, что существует довольно много классов, которые предоставляют как переменные класса, так и собственные функции получения. например.
class FormMixin(object):
initial = {}
def get_initial(self):
return self.initial
Это дизайнерское решение имеет смысл, поскольку таким образом вы можете вызвать super()
в переопределяющем методе расширяющегося класса.
Характеристики
В моем проекте есть определенные значения, которые я мог бы иногда переопределить, используя простое значение, но иногда их приходится генерировать динамически.Сначала я создал методы, подобные приведенным выше, но потом подумал, что, возможно, свойства — лучший способ сделать это.
class MyBaseView(OtherView):
counter = None
class MyExtendingView(MyBaseView):
counter = 5
class MyOtherExtendingView(MyBaseView):
@property
def counter(self):
return self.other_function()
экземпляр.__dict__
Я планирую использовать эти значения внутри шаблона.Я передаю экземпляры расширяющихся представлений в шаблон и отображаю атрибуты следующим образом:
context['class_instances'] = [MyExtendingView(), MyOtherExtendingView()]
{% for instance in class_instances %}
{{ instance.counter|default:'' }}
{% endfor %}
Поскольку это шаблон и на самом деле не имеет значения, является ли атрибут экземпляра значением или функцией, я также мог бы написать свои классы следующим образом:
class MyExtendingView(MyBaseView):
counter = 5
class MyOtherExtendingView(MyBaseView):
def counter(self):
return self.other_function()
А def counter
заменит старый атрибут на основе значения в instance.__dict__
.
Вопрос
Чтобы перейти к вопросу, какой из перечисленных подходов является лучшим выбором?
- Метод получения хорош, поскольку позволяет
super()
-вызов родительской функции-получателя, но в большинстве моих случаев это, вероятно, никогда не понадобится. - Подход, основанный на свойствах, намного проще и требует написания меньшего количества кода.я не могу
super()
-вызовите функцию свойства родителя.В большинстве случаев мне не понадобится такое поведение, но могут быть случаи, когда мне понадобитсяsuper()
функциональность, поэтому будет смесь простых атрибутов, которые можно переопределить с помощью свойств и пользовательских функций получения. - Последний подход требует еще меньше кода, чем подход, основанный на свойствах, но я сомневаюсь, что это хороший стиль.
Решение
Подход, основанный на свойствах, намного проще и требует написания меньшего количества кода.Однако я не могу super() вызвать функцию свойства родителя.
На самом деле вы можете получить доступ к родительским свойствам через super()
:
class A(object):
@property
def prop(self):
return 'A.prop'
class B(A):
@property
def prop(self):
return '%s - %s' % (super(B, self).prop, 'B.prop')
>>> b = B()
>>> b.prop
'A.prop - B.prop'