[that link is going down -- hence, I'm pasting the contents below] Django ORM does not support inheritance. Inheritance is a good thing. Often I want some of the database models to share some common fields and the same manager. For example consider the case of adding the delete proxy.
class RetainDeletesMixin(object): class NonDeleted(models.Manager): def get_query_set(self): return super(NonDeleted, self).get_query_set().filter( delete_flag=0) delete_flag = models.IntegerField(null=True, blank=True, default=0) objects = NonDeleted() def delete(self): self.delete_flag = 1 self.save() class Item(RetainDeletesMixin, models.Model): ... Here we are extending the model Item by adding a mixin that overrides the delete method - so that when we do item.delete() the model is not actually deleted but merely flagged (delete_flag=1) so. This means the get_query_set method should also be told not to return the flagged models. In Python speak, >>> items = Item.objects.all() >>> item = items[0] >>> len(items) 1 >>> item.delete_flag 0 >>> item.delete() >>> item.delete_flag 1 >>> len(Item.objects.all()) 0 >>> But this will not work. Django does not consider delete_flag, which is inherited from RetainDeletesMixin, as a database column at all. So I came up with the following metaclass hack which enables you to design the django models based on the inheritance pattern like the above, class RetainDeletesMixin(object): class NonDeleted(models.Manager): def get_query_set(self): # Ideally, we should be using `super` here but we don't because # the variable `NonDeleted` will not be accessible once we # 'copy' this class in the metaclass. return models.Manager.get_query_set(self).filter( delete_flag=0) delete_flag = models.IntegerField(null=True, blank=True, default=0) objects = NonDeleted() def delete(self): self.delete_flag = 1 self.save() def django_extends(base): class ProxyMetaClass(models.Model.__metaclass__): def __new__(cls, name, bases, attrs): # The following attributes must be moved *prior* to deferring # execution to the models.Model's metaclass, because they # will be manipulated by __new__ # - models.fields.Field instances # - objects (ModelManager) for key in dir(base): if not key.startswith('_'): obj = getattr(base, key) if isinstance(obj, models.fields.Field) or \ key == 'objects': attrs[key] = obj delattr(base, key) # Delete objects that have attribute 'contribute_to_class' # for otherwise that will break in # base.py:Model.add_to_class # Eg: inner classes inherited from models.Manager elif hasattr(obj, 'contribute_to_class'): delattr(base, key) return super(ProxyMetaClass, cls).__new__(cls, name, tuple([base]+list(bases)), attrs) frame = sys._getframe(1) frame.f_locals['__metaclass__'] = ProxyMetaClass class Item(models.Model): django_extends(RetainDeletesMixin) ... What this basically does is - copy the database fields and objects from the base class (RetainDeletesMixin) to the derived class (Item) so that Django will recognize it upon processing in ModelBase. It also makes RetainDeletesMixin a base class of Item. I have not tested this code extensively, but it works for the models that I have written in our application. On Dec 19, 1:53 pm, Sridhar Ratnakumar <[EMAIL PROTECTED]> wrote: > I wanted to share this little hack of mine - conceptual (not database- > based)inheritancefordjango:http://nearfar.org/blog/django-model-inheritance.html --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~----------~----~----~----~------~----~------~--~---