I'm creating a Django app that uses some inheritance in it's model, mainly because I need to assign everything a UUID and a reference so I know what class it was. Here's a simplified version of the base class:
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)
I'd like to make sure that objmodule, objclass, and uuid are set automatically. I've learned from this post that it's a bad idea to do that by writing my own constructor, and that I'm better off writing a factory function. So now my BaseElement and ChildElement looks like this:
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
This works. I can call ChildElement.create(somefield="foo")
and I will get an appropriate object with uuid
, objmodule
, and objclass
fields set correct. However, as I go through and create more classes like ChildElement2
and ChildElement3
, I'm finding that I'm inserting the exact same static factory function. This grates on me because code duplication is bad.
With normal methods I'd just insert the create
factory function in BaseElement
, however, I can't do that here because I don't have a handle to self (because it hasn't been created yet) to get information about the class of the object that invoked the method.
Is there a way that I can migrate this factory into the BaseElement
class so I don't have to duplicate this code everywhere and still have it so it automatically sets the values of uuid
, objmodule
, and objclass
?
Factory method is a creational design pattern which solves the problem of creating product objects without specifying their concrete classes. The Factory Method defines a method, which should be used for creating objects instead of using a direct constructor call ( new operator).
Factory functions are mainly used when the user wants to initialize the object of a class multiple times with some assigned value or static values. It makes the process easy since we just have to call this function and retrieve the new object created.
A Class Factory is a function that creates and returns a class. It is one of the powerful patterns in Python.
DjangoModelFactory is a basic interface from factory_boy that gives "ORM powers" to your factories. It's main feature here is that it provides you with a common "create" and "build" strategies that you can use to generate objects in your tests.
If you make create()
a @classmethod
instead of @staticmethod
, you'll have access to the class object, which you can use instead of referring to it by name:
@classmethod
def create(cls, *args, **kwargs):
obj = cls(*args, **kwargs)
obj.set_defaults()
return obj
This is now generic and can go on the base class instead of each child class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With