Наследование и фабрика функционируют в Python и Django

Я создаю приложение Django, которое использует некоторое наследование в, он - модель, главным образом потому что я должен присвоить всему UUID и ссылку, таким образом, я знаю, каково класс это было. Вот упрощенная версия базового класса:

class BaseElement(models.Model):
    uuid = models.CharField(max_length=64, editable=False, blank=True, default=lambda:unicode(uuid4()))
    objmodule = models.CharField(max_length=255, editable=False, blank=False)
    objclass = models.CharField(max_length=255, editable=False, blank=False)

class ChildElement(BaseElement):
    somefield = models.CharField(max_length=255)

Я хотел бы удостовериться, что objmodule, objclass, и uuid установлены автоматически. Я узнал из этого сообщения, что это - плохая идея сделать это путем записи моему собственному конструктору, и что я - более обеспеченная запись функции фабрики. Таким образом, теперь мой BaseElement и ChildElement похожи на это:

class BaseElement(models.Model):
    uuid = models.CharField(max_length=64, editable=False, blank=True, default=lambda:unicode(uuid4()))
    objmodule = models.CharField(max_length=255, editable=False, blank=False)
    objclass = models.CharField(max_length=255, editable=False, blank=False)

    def set_defaults(self):
        self.objmodule = unicode(self.__class__.__module__)
        self.objclass = unicode(self.__class__.__name__)
        self.uuid = unicode(uuid4())

class ChildElement(BaseElement):
    somefield = models.CharField(max_length=255)

    @staticmethod
    def create(*args, **kwargs):
        ce = ChildElement(*args, **kwargs)
        ce.set_defaults()
        return ce

Это работает. Я могу звонить ChildElement.create(somefield="foo") и я получу соответствующий объект с uuid, objmodule, и objclass полевой корректный набор. Однако, поскольку я прохожу и создаю больше классов как ChildElement2 и ChildElement3, Я нахожу, что вставляю ту же самую статическую функцию фабрики. Это трет на мне, потому что дублирование кода плохо.

С нормальными методами я просто вставил бы create функция фабрики в BaseElement, однако, я не могу сделать этого здесь, потому что у меня нет дескриптора к сам (потому что он еще не был создан) получить информацию о классе объекта, который вызвал метод.

Есть ли способ, которым я могу переместить эту фабрику в BaseElement класс, таким образом, я не должен копировать этот код везде и все еще иметь его так он автоматически, устанавливает значения uuid, objmodule, и objclass?

5
задан Community 23 May 2017 в 12:03
поделиться

2 ответа

Если вы сделаете create () @classmethod вместо @staticmethod , у вас будет доступ к классу объект, который вы можете использовать вместо того, чтобы ссылаться на него по имени:

@classmethod
def create(cls, *args, **kwargs):
    obj = cls(*args, **kwargs)
    obj.set_defaults()
    return obj

Теперь это общий и может относиться к базовому классу вместо каждого дочернего класса.

7
ответ дан 14 December 2019 в 01:09
поделиться

Я думаю, вам лучше было бы вместо этого переопределить сохранение в вашем BaseElement. Затем при сохранении вы можете установить эти поля. Это будет примерно так:

class MyBase(models.Model):
    uuid = models.CharField(max_length=64, editable=False, blank=True,
        default=lambda:unicode(uuid4()))
    objmodule = models.CharField(max_length=255, editable=False, blank=False)
    objclass = models.CharField(max_length=255, editable=False, blank=False)

    def save(self):
        if not self.id:
            self.objmodule = unicode(self.__class__.__module__)
            self.objclass = unicode(self.__class__.__name__)
            self.uuid = unicode(uuid4())
        super(self.__class__.__base__, self).save()

class InheritedFromBase(MyBase):
    new_field = models.CharField(max_length=100)

Я тестировал это, и похоже, что он делает то, что вы ищете. Мне удалось создать объект «InheritedFromBase» с нужными вам полями без большого дублирования кода.

2
ответ дан 14 December 2019 в 01:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: