Django Model Mixins: inherit from models.Model or from object?

Python

Python Problem Overview


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: https://stackoverflow.com/questions/3263417/django-abstract-models-vs-simple-python-mixins-vs-python-abcs

Python Solutions


Solution 1 - Python

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.

Solution 2 - Python

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.

Solution 3 - Python

This looks like a job for an http://docs.djangoproject.com/en/dev/topics/db/models/#id6">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.

Solution 4 - Python

When you inherits from plain Python object South doesn't create a migration so you can't use this approach

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionhoplaView Question on Stackoverflow
Solution 1 - PythonjsdaltonView Answer on Stackoverflow
Solution 2 - PythonDaniel RosemanView Answer on Stackoverflow
Solution 3 - PythonIgnacio Vazquez-AbramsView Answer on Stackoverflow
Solution 4 - PythonkharandziukView Answer on Stackoverflow