3 uses for functools.partial in Django2021-05-05
functools.partial is a great tool that I feel is underused.
(If you don’t know what
partial is, check out PyDanny’s explainer.)
Here are a few ways I’ve used
partial in Django projects.
1. Making reusable fields without subclassing
It’s common to have field definitions the same across many models, for example a
created_at field tracking instance creation time.
We can do create such a field like so:
Copying this between models becomes tedious, and makes changing the definition hard.
One solution to this repetition is to use a base model class or mixin. This is fine, but it scatters the definition of a model’s fields, prevents local customization of arguments, and can lead to complex inheritance hierarchies.
Another solution is to create a subclass of
DateTimeField and add it to every model.
This works well but can lead to complications with migrations, as the migration files will refer to the subclass by import and we will need to update them all if we refactor.
We can instead use
partial to create a “cheap subclass” of the field class.
Our models will still directly use
DateTimeField, but with some arguments pre-filled.
partial also allows us to replace the pre-filled arguments, so we can override them when needed:
We can also apply this technique to fields in forms, Django REST Framework serializers, etc.
2. Creating many
upload_to callables for
When using the model
FileField, or subclasses like
ImageField, one can pass a callable as the
upload_to argument to calculate the destination path.
This allows us to arrange the media according to whatever scheme we want.
If we are using multiple such fields that share some logic for
upload_to, we can use
partial to avoid creating many similar functions.
For example, if we had a user model that allows uploading two types of image into their respective subfolders:
3. Pre-filling view arguments in URL definitions
Sometimes we might have a single view that changes behaviour based on the URL mapping to it.
In such a case we can use
partial to set parameters for the view, without creating wrapper view functions.
For example, imagine we have a user profile view, for which we are currently working on “version two” functionality:
We can map two URL’s to the
profile function view, switching
True for the a preview URL:
I hope this has taught you something new—at least partially.
Want better tests? Check out my book Speed Up Your Django Tests which teaches you to write faster, more accurate tests.
One summary email a week, no spam, I pinky promise.
- A Guide to Python Lambda Functions
- How to Combine Two Python Decorators
- Better Python Decorators with wrapt
Tags: python, django
© 2021 All rights reserved.