Я создаю приложение 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
?
Если вы сделаете create ()
@classmethod
вместо @staticmethod
, у вас будет доступ к классу объект, который вы можете использовать вместо того, чтобы ссылаться на него по имени:
@classmethod
def create(cls, *args, **kwargs):
obj = cls(*args, **kwargs)
obj.set_defaults()
return obj
Теперь это общий и может относиться к базовому классу вместо каждого дочернего класса.
Я думаю, вам лучше было бы вместо этого переопределить сохранение в вашем 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» с нужными вам полями без большого дублирования кода.