In my recent Boost Your Django DX update, I added a new chapter on debuggers. Here’s an extra technique I didn’t finish in time for the update, but I will include it in the next one.
Python’s breakpoint() function opens its debugger, pdb, which pauses the program and allows you to inspect and modify things. Let’s look at an example of using it within a Django view, from a sample project included in Boost Your Django DX.
Heavy refactoring of models can leave a Django project with “ghost tables”, which were created for a model that was removed without any trace in the migration history. Thankfully, by using some Django internals, you can find such tables.
git rev-list lists details about commits (also known as “revisions”, hence the name). Its --count option outputs the count of commits in the given range. Pass it @, the short alias for HEAD, to count commits on the current branch:
I have just released the second update to Boost Your Django DX, my book of developer experience (DX) recommendations for Django projects. This update contains a new chapter, changes some recommended tools, and upgrades to Python 3.13 and Django 5.1. Overall, the book is 45 pages longer, now totalling 326!
Git doesn’t store reversion links between commits. It only relies on commit messages to track this information. When you run git revert, the default message includes a line about the reverted commit:
uv is a new, fast Python packaging tool. (I believe it is pronounced as written, “uhv”, rather than spelt out like “you-vee”. This saves a syllable, fitting the tool’s ethos of speed.)
Django’s test client provides two methods to log in a user: login() and force_login(). The latter one is faster because it bypasses the authentication backend, including password hashing, and just sets a session to have the user logged in. Typically, you’d want to use it in setUp() like this:
Django provides us with a rich set of view decorators. In this post, we’ll look at a technique for hoisting repeated use of these decorators to reduce repetition.
Recently, I built a Microsoft Teams bot for a client, inside their Django project. It wasn’t fun or easy, but the experience did increase my resiliency as a developer. I also went into this forewarned by my wife, a product manager also known as “the integration queen”, who has experienced the difficulties of the Teams API first-hand.
git shortlog generate statistics about the commits in a repository, intended to help generate project release notes. By default, it groups commits by author, but it can use other fields too. Use it for a more powerful dissection of a repository than tools like GitHub’s Insights tab.
Django’s SECRET_KEY setting is used for cryptographic signing in various places, such as for session storage and password reset tokens. This makes keeping it secure a high priority since an attacker with the key could forge things like password reset tokens.
tracemalloc is Python’s standard library module for tracking memory allocations. It has many bells and whistles for detailed analysis, allowing you to slice allocations by file and line or compare snapshots. But for simple purposes, displaying the total memory allocated is sufficient, which is what this recipe does:
argparse, the standard library module that Django uses for parsing command line options, supports sub-commands. These are pretty neat for providing an expansive API without hundreds of individual commands. Here’s an example of using sub-commands in a Django management command:
Django requires every change to model fields and meta classes to be reflected in database migrations. This applies even to things that don’t typically affect the database, such as Field.choices. When iterating on code, it’s easy to make a model change and forget to update the migrations accordingly. If you don’t have any protection, you might even deploy code that crashes due to out-of-date migrations!
Django and other frameworks often allow you to configure classes, functions, or modules to import using strings. To do the same in your own code, use pkgutil.resolve_name() from the standard library (added in Python 3.9):
Sometimes, you want to test a function that uses an inner import and mock that imported object. For example, say you wanted to mock dig() in this example: