Reputation: 8336
I have a Base class for many Subclasses, and the only thing changing within the subclasses is a certain method (the template pattern). However I am stuck and can't get it to work.
class Base(models.Model):
_value = models.CharField(max_length=200)
_name = models.CharField(max_length=200)
user = models.ForeignKey(User, related_name="some_set")
#used as a property
def value():
def fget(self):
self.refresh()
return self._value
def refresh(self):
raise NotImplementedError("..")
class Subclass1(Base):
def refresh(self):
self._value = some_val
class Subclass2(Base):
def refresh(self):
self._value = some_other_val
I would love to be able to treat the entire related set as the same entity, and call the value property on each, with each deferring to its own implemented version of refresh, i.e.
for x in user.some_set.all():
print x.value
but at this point it doesn't seem possible, even with removing refresh in the superclass. I've also thought of using the Strategy pattern and use a ForeignKey relationship to call the method, but I would still have to have a base class in the ForeignKey that the subclasses derive from.
Upvotes: 2
Views: 951
Reputation: 8336
I ended up using the Strategy pattern with a GenericForeignKey
class Base(models.Model):
_name = models.CharField(max_length=200)
user = models.ForeignKey(User, related_name="some_set")
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
strategy = GenericForeignKey()
#used as a property
def value():
def fget(self):
return self.strategy.value
class Strategy1(models.Model):
#some other definitions
def value():
def fget(self):
return some_var
class Strategy2(models.Model):
#some other definitions
def value():
def fget(self):
return some_other_var
Which allowed me to do for x in user.some_set.all(): print x.value
Upvotes: 0
Reputation: 3806
use Proxy Models
from the doc
Sometimes, however, you only want to change the Python behavior of a model – perhaps to change the default manager, or add a new method.
This is what proxy model inheritance is for: creating a proxy for the original model. You can create, delete and update instances of the proxy model and all the data will be saved as if you were using the original (non-proxied) model. The difference is that you can change things like the default model ordering or the default manager in the proxy, without having to alter the original.
Upvotes: 4
Reputation: 3542
I might be missing the point, but have you tried Django Model Utils?
https://bitbucket.org/carljm/django-model-utils/src
If you look at the inheritance manager and make the relevant changes to your model, you should then be able to query as per:
entities = Base.objects.filter(user=my_user_obj).select_subclasses()
for entity in entities:
print entity.value
Upvotes: 1