Mixins for Fun and Profit

There are certain places where heavy use of mixins can save a ton of time or cognitive load. A use case that came up recently was in a Django project where several class-based views needed to serve only traffic within our intranet. An existing middleware does this check, raising an Http404 if a request comes from outside the network. Adding that functionality to our classes was fairly easily, using decorator_from_middleware and method_decorator on the views’ dispatch methods:

from django.utils.decorators import decorator_from_middleware, method_decorator
from django.views import generic
from app import middleware

network_protected = decorator_from_middleware(
middleware.NetworkProtectionMiddleware
)

@method_decorator(network_protected, name='dispatch')
class SecretView(generic.View):
...

However, when I added a second piece of functionality I had to decorate those views too. I was getting a little tired of decorating.

Happy Holidays

Instead, I refactored the network protection integration into a mixin, allowing all our class-based views to inherit from this as they saw fit:

from django.utils.decorators import decorator_from_middleware, method_decorator
from django.views import generic

network_protected = decorator_from_middleware(
middleware.NetworkProtectionMiddleware
)

class NetworkProtectionMixin(object):
@method_decorator(network_protected)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)

class SecretView(NetworkProtectionMixin, generic.View):
...

A similar approach can be used for Django’s permissions, authentication, and more. This is powerful, and when used correctly can result in wonderfully expressive code. It also reduces complexity, allowing easier unit testing and comprehension.

At the end of the day, mixins are a DRY way to architect code, abstracting potentially complex functionality so that developers can concentrate more fully on the task at hand instead of propping up all the pieces. Rejoice!