Using just with Django

Jeff Triplett convinced me to take a look at just as a command automation tool - sort of an alternative to Make, except with a focus on commands rather than managing build dependencies.

I really like it, and I've started using it for my own Django projects.

Installing with Homebrew

Installing just on my Mac was easy:

brew install just

The tool is written in Rust and provides binaries for basically everything - there are plenty more ways to install it.

Writing a Justfile

The Justfile defines which commands just makes available. When you run just it looks for a Justfile in the current or any parent directory.

Commands in that file are run as if the working directory was the directory containing the Justfile.

Here's the file I've built so far for my current Django project. The project already uses pipenv and has some slightly convoluted environment requirements - just is a perfect tool for patching over those so I don't have to think about them any more.

I added some comments to help explain what's going on:

# Using export here causes this DATABASE_URL to be made available as an
# environment variable for any command run by Just
export DATABASE_URL := "postgresql://localhost/myproject"

# The first command is the default if you run "just" with no options.
# I used *options to allow this to accept options, which means I can run:
#
#    just test -k auth --pdb
#
# To pass the "-k auth --pdb" options to pytest

@test *options:
  pipenv run pytest {{options}}

# This starts the Django development server with an extra environment variable
# I also print out a URL to the console so I can click on it without
# remembering which extra item I configured in /etc/hosts for this project
@server:
  echo "Starting http://myapp.local:8000/"
  DJANGO_SETTINGS_MODULE="config.localhost" pipenv run ./manage.py runserver

# I added this so I could run things like "just manage migrate" to run migrations
@manage *options:
  DJANGO_SETTINGS_MODULE="config.localhost" pipenv run ./manage.py {{options}}

The @ before a command name causes that command to NOT output each line to the console before it is executed, which I found is usually what I wanted.

Here's what that example looks like without the comments: it's pretty succinct.

export DATABASE_URL := "postgresql://localhost/myproject"

@test *options:
  pipenv run pytest {{options}}

@server:
  echo "Starting http://myapp.local:8000/"
  DJANGO_SETTINGS_MODULE="config.localhost" pipenv run ./manage.py runserver

@manage *options:
  DJANGO_SETTINGS_MODULE="config.localhost" pipenv run ./manage.py {{options}}

What this lets me do

To list all options:

% just --list
Available recipes:
    manage *options
    server
    test *options

To run all of my tests:

just

To run specific tests

just test -k name

To run tests, stopping at the first error and opening a debugger:

just test -x --pdb

To start my development server running:

just server

To run migrations:

just manage migrate

To run ./manage.py shell:

just manage shell

More examples

I found Jeff's scripts-to-rule-them-all example really helpful in learning how to use just.

The official README is excellent.

Created 2022-06-06T14:24:37-07:00 · Edit