Django Model Mixins: inherit from models.Model or from object?
This is a question about Python Mixins that might be useful in general. I'm just using Django models as that is the use-case I'm most familiar with.
Should a mixin inherit from the class it is designed to mix-in with or from 'object'?
Examples by code, what is more correct or better, or better depending on what you want to achieve?
This
class TaggingMixin(models.Model):
tag = models.ForeignKey(Tag)
class Meta:
abstract = True
class MyModel(models.Model, TaggingMixin):
title = models.CharField(max_length=100)
Or this:
class TaggingMixin(object):
tag = models.ForeignKey(Tag)
class Meta:
abstract = True
class MyModel(models.Model, TaggingMixin):
title = models.CharField(max_length=100)
I think inheriting from object is the right way. But I'm seeing examples of the first case all over the net...
EDIT: I've moved my follow up question to a separate question: Django Abstract Models vs simple Python mixins vs Python ABCs
Django does a lot of meta magic when it comes to its model classes, so unfortunately the usual approach to mixins as suggested in Daniel Roseman's answer -- where they inherit from object
-- does not work well in the Django universe.
The correct way to structure your mixins, using the example provided, would be:
class TaggingMixin(models.Model):
tag = models.ForeignKey(Tag)
class Meta:
abstract = True
class MyModel(TaggingMixin):
title = models.CharField(max_length=100)
Important points here being:
- Mixins inherit from
model.Model
but are configured as an abstract class. - Because mixins inherit from
model.Model
, your actual model should not inherit from it. If you do, this might trigger a consistent method resolution order exception.
I would recommend that it inherits from object
. That way you can ensure that it only provides those methods and attributes you actually define explicitly.
Also, you should always ensure that you put the mixin class first when defining your concrete class. Python's resolution rules mean that the superclasses are searched in order of their definition in the class declaration, and resolution stops when a matching attribute is found. So if your mixin defines a method that is also defined by the main superclass, your mixin method won't be found.
This looks like a job for an abstract model.
EDIT:
Those are not mixins per se. Or rather, they do not need to be. You can derive from an abstract model directly.
When you inherits from plain Python object South doesn't create a migration so you can't use this approach