Archives for 2025| adamj.eu
Here’s a little tip based on some work that I did recently. The project has a URL pattern where the first part of the URL matches the current role the user is viewing the site as. Let’s say the roles are “chef”, “gourmand”, and “foodie”—example URLs might …| Adam Johnson
Sometimes, it’s useful to branch the behaviour of your code based on the version of a package that you have installed. This may be to support an upgrade in your project, or for your own package to support different versions of a dependency. Some Python packages provide a top-level …| Adam Johnson
Within Django’s popular admin site, you can override ModelAdmin.get_queryset() to customize the queryset used by the admin views. It’s often used for performance optimizations, such as adding a select_related() call to batch-fetch related objects:| adamj.eu
All Tags| adamj.eu
There you are, minding your own business, rebasing your branch and… surprise! A merge conflict!| adamj.eu
Archives for 2022| adamj.eu
I’ve found it useful, on occasion, to iterate through all registered URL patterns in a Django project. Sometimes this has been for checking URL layouts or auditing which views are registered. In this post, we’ll look at a pattern for doing that, along with an example use case …| Adam Johnson
Recently, I was working in a new repository and found the git blame output often pointed back to a large repository-wide formatting commit (applying Black to all Python files). To ignore this commit in git blame, I added its SHA to a .git-blame-ignore-revs file, per this documentation: # Format everything with …| Adam Johnson
If you’ve written a Python script that outputs a lot of data, then piped that output into another command that only reads part of it, you might have encountered a BrokenPipeError. For example, take this script: foriinrange(10_000):print(f"This is line {i} ") When piped …| Adam Johnson
Typically, we share repositories through a Git host, like GitHub, allowing others to clone the repository to get a copy. But sometimes that’s not an option, for example when trying to get someone started on your project when corporate onboarding processes take days to grant GitHub access.| adamj.eu
If you make a mistake whilst rebasing, it might seem hard to undo. But with git reflog, you can find the original commit SHA and revert back to it. Let’s see how with an example.| adamj.eu
Have you ever accidentally committed a bunch of junk created by your OS, like Thumbs.db files from Windows, or .DS_Store files from macOS? Or, have you joined a project, and for one of your first commits, added rules to the .gitignore file for your text editor’s project files? If so, this post is for you! You can avoid such pain or busywork by making a global ignore file.| adamj.eu
You started a new branch, worked hard on initial commits, and you’re ready to send it for review. You try to push and:| adamj.eu
By default, if you mistype a Git command, it will list similar commands that you might have meant:| adamj.eu
From Django 5.2 (April 2025), the runserver management command outputs a warning: $ ./manage.pyrunserver ...Starting development server at http://127.0.0.1:8000/Quit the server with CONTROL-C.WARNING: This is a development server. Do not use it in a production setting. Use a production WSGI or …| Adam Johnson
I recently released a new package called inline-snapshot-django. It’s a tool for snapshot testing SQL queries in Django projects, described shortly.| adamj.eu
Here are some issues I’ve seen crop up several times in Django projects using Celery. They probably apply with other task queues, I simply haven’t used them so much.| adamj.eu
This post is a PSA on the somewhat unintuitive way Field.choices works in Django.| adamj.eu
On several Django projects I’ve worked on, there has been a requirement for performing database modifications beyond Django migrations. For example:| adamj.eu
Archives for 2020| adamj.eu
A neat testing pattern is writing common tests in a base class and then applying them to multiple objects through subclassing. Doing so can help you test smarter and cover more code with less boilerplate.| adamj.eu
You may encounter this warning when cloning a Git repository:| adamj.eu
In Python, a mixin class is a class that is not intended to be used directly, but instead “mixed in” to other classes through multiple inheritance. Mixins are not really a language feature but more of a conventional pattern allowed by Python’s multiple inheritance rules. Unfortunately, adding type hints to mixin classes can be tricky because they implicitly require subclasses to fit a certain shape.| adamj.eu
Git: find the largest commits| adamj.eu
Many Git commands output “advice”, with hints about which commands you could run next. Most notably, git status gives you advice for what to do about files in each state:| adamj.eu
robots.txt is a standard file to communicate to “robot” crawlers, such as Google’s Googlebot, which pages they should not crawl. You serve it on your site at the root URL /robots.txt, for example https://example.com/robots.txt.| adamj.eu
Python: my new uv setup for development| adamj.eu
Archives for 2024| adamj.eu
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.| adamj.eu
Django: Introducing Djade, a template formatter| adamj.eu
When we write custom management commands, it’s easy to write integration tests for them with call_command(). This allows us to invoke the management command as it runs under manage.py, and retrieve the return code, standard output, and standard error. It’s great, but has some overhead, making our tests slower than necessary. If we have logic separated out of the command’s handle() method, it improves both readability and testability, as we can unit test it separately.| adamj.eu
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:| adamj.eu
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!| adamj.eu
Here’s a code snippet I often type:| adamj.eu
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:| adamj.eu
I have just released an update to my book Boost Your Git DX, six months after its initial release. This update adds some extra content and has a bunch of edits based on reader feedback. The PDF is now ten pages longer, for a total of 363.| adamj.eu
git bisect efficiently searches for a commit responsible for changing a given behaviour. git log lets you see when a given file or line changed, but that’s often insufficient when the cause of some change is unclear. In such cases, git bisect shines, as it lets you check your running system.| adamj.eu
Contrary to common belief, Git doesn’t store diffs. It actually stores snapshots of whole files, heavily compressed to reduce redundancy. Then when displaying a diff is required, git diff generates it on the fly.| adamj.eu
Global Privacy Control (GPC) is a specification for web browsers to signal website operators not to share or sell the user’s data. This signal is intended to exercise legal data privacy rights such as those provided by the California Consumer Privacy Act (CCPA) or the EU’s General Data Protection Regulation (GDPR). While GPC is a proposal, support has been implemented in Firefox and several other privacy-focused browsers and extensions.| adamj.eu