Django - получение оригинального имени класса в абстрактном методе - PullRequest
0 голосов
/ 16 мая 2018

То, что я пытаюсь сделать, лучше всего описать на следующем примере:

class MyAbstractClass(models.Model):
    abstract_field = IntegerField()

    class Meta:
        abstract = True

    def abstract_method(self):
         # THE ISSUE LIES IN THE LINE BELOW 
         ParentClass.objects.filter(..).update(....)
         return self

class InheritedClass(MyAbstractClass):
     # Field

def my_view(request):
    obj = InheritedClass.objects.get(id=1)
    obj.save()
    return obj

Так что, в принципе, вопрос в том, есть ли в abstract_method какой-либо способ сказать Django, что он обращается к вызывающему классу (то есть InheritedClass)?

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Технический ответ: Ну, довольно просто да:

def abstract_method(self):
     type(self).objects.filter(..).update(....)
     return self

Обратите внимание, что это методы Python, вызываемые с "вызывающим" объектом (объектом, для которого вызывается метод) в качестве первого параметра, и все атрибуты поиска будут происходить с этим объектом и его классом - иначе наследование просто не будет работать вообще.Единственная специфическая для django часть здесь - это то, что Django не позволяет вам использовать ModelManager на экземпляре модели, поэтому вам нужно явно получить класс объекта, который возвращается type(self).

НО:

Соображения о стиле кодирования

Django рекомендует, чтобы методы модели, действующие на всю таблицу, принадлежали ModelManager (в отличие от методов, действующих только на текущей строке, которые должны быть реализованы как простыеметоды), так как ваш метод, очевидно, действует на всю таблицу, может быть лучше, чем метод ModelManager.

Я говорю «может», потому что есть серая область, где обновление одной строки подразумевает также обновление некоторых других строк - типичный пример, когда у вас есть флаг, который всегда должен быть установлен только для одной записи, поэтому вы такжехочу сбросить его на всех других записях.(Конечно) в вашем вопросе недостаточно контекста, чтобы сказать, какой из них является правильным выбором.

0 голосов
/ 16 мая 2018

Вы можете просто сделать self.objects.filter(...).update(..)

Абстрактный класс просто реализует методы, которые наследуются его конкретным классом, здесь InheritedClass. Поэтому все для методов и полей доступно в наследующем классе.

Однако для этого случая я бы посоветовал вам взглянуть на создание собственного менеджера моделей. Методы в модели предназначены для работы с полями этой конкретной строки, тогда как менеджеры предназначены для работы в масштабе всей таблицы, как описано в методы модели

Определение пользовательских методов в модели для добавления пользовательских функций на уровне строк к вашим объектам. В то время как методы Manager предназначены для выполнения «табличных» задач, методы модели должны действовать на конкретный экземпляр модели.

Если у вас есть метод, выполняющий фильтрацию в методе модели, это запах кода, и он принадлежит пользовательскому менеджеру.

...