Estoy creando una aplicación Django que usa algo de herencia en su modelo, principalmente porque necesito asignar todo un UUID y una referencia para saber qué clase era. Aquí hay una versión simplificada de la clase base:Herencia y funciones de fábrica en Python y Django
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)
me gustaría asegurarse de que objmodule, objclass y UUID se ajustan automáticamente. Aprendí de this post que es una mala idea escribir mi propio constructor y que es mejor escribir una función de fábrica. Así que ahora mi BaseElement y ChildElement se ve así:
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
Esto funciona. Puedo llamar al ChildElement.create(somefield="foo")
y obtendré un objeto apropiado con los campos uuid
, objmodule
y objclass
establecidos correctos. Sin embargo, a medida que avanzo y creo más clases como ChildElement2
y ChildElement3
, me doy cuenta de que estoy insertando exactamente la misma función de fábrica estática. Esto me irrita porque la duplicación de código es mala.
Con los métodos normales, simplemente inserta la función de fábrica create
en BaseElement
, sin embargo, no puedo hacer eso porque no tengo un identificador (porque no se ha creado aún) para obtener información sobre la clase del objeto que invocó el método.
¿Hay una manera de que pueda migrar esta fábrica en la clase BaseElement
por lo que no tiene que duplicar este código en todas partes y todavía tienen que por lo que ajusta automáticamente los valores de uuid
, objmodule
y objclass
?
Eso es exactamente lo que estaba buscando. Gracias por recordarme sobre '@ classmethod'. No es algo que use muy a menudo. – Pridkett
En Python, rara vez hay un buen caso de uso para '@ static method.-Es probable que deba usarlo con menos frecuencia, si es que lo hace alguna vez. A menudo, si algo no es un método @ @ classmethod, es más apropiado como una función simple de nivel superior en un módulo. –