Skip to content

Instantly share code, notes, and snippets.

@ajcerejeira
Last active October 17, 2022 23:22
Show Gist options
  • Save ajcerejeira/c043a441f9078ce996b5a09cb98c130c to your computer and use it in GitHub Desktop.
Save ajcerejeira/c043a441f9078ce996b5a09cb98c130c to your computer and use it in GitHub Desktop.
(Ab)using Makefiles in Django projects
# Lightning talk @ DjangoCon EU 2022
# Afonso Cerejeira <github.com/ajcerejeira>
# Intro
# =====
#
# - Makefiles are a set of rules for building targets based on prerequisites;
# - Usually both targets and prerequisites represent filenames;
# - Makefiles define dependency graphs;
# Project setup
# =============
VENV := .venv
PYTHON := $(VENV)/bin/python
$(PYTHON):
python -m venv $(VENV)
.PHONY: install
install: $(VENV)/.install
$(VENV)/.install: $(PYTHON) requirements.txt
$(PYTHON) -m pip install -r requirements.txt
touch $@ # file name of the target of the rule, in this case '.venv/.install'
# Usage:
#
# $ make install
# python -m venv .venv
# .venv/bin/python -m pip install -r requirements.txt
# ...
# touch .venv/.install
#
# make only runs install when requirements.txt is updated:
# Automatically installing Python programs
# ========================================
# Special rule to automatically install binary targets, (e.g, dev tools)
# - '%' is a placeholder to be substituted in the target
# - '$@' expands to the name of the target (i.e, '$(VENV)/bin/...')
# - 'notdir' is function that extracts the basename of a file
$(VENV)/bin/%: $(PYTHON)
$(PYTHON) -m pip install $(notdir $@)
# Usage:
# $ make .venv/bin/pylint
# python -m venv .venv
# .venv/bin/python -m pip install pylint
# Collecting pylint
# Linting and formatting
# ======================
BLACK := $(VENV)/bin/black
ISORT := $(VENV)/bin/isort
DJHTML := $(VENV)/bin/djhtml
PYLINT := $(VENV)/bin/pylint
.PHONY: format
format: $(BLACK) $(ISORT) $(DJHTML)
$(BLACK) .
$(ISORT) .
$(DJHTML) -i templates/
.PHONY: lint
lint: $(PYLINT)
$(PYLINT) .
# Testing
# =======
COVERAGE := $(VENV)/bin/coverage
.PHONY: test
test: install $(COVERAGE)
$(COVERAGE) run manage.py test
$(COVERAGE) report
$(COVERAGE) html
# Automating Docker workflows
# ===========================
.ONESHELL: docker
.SILENT: docker
docker: .SHELLFLAGS = run --rm --entrypoint /bin/bash ubuntu -c
docker: SHELL := docker
docker:
echo "hello, container world!"
# Embedding Python scripts in the Makefile
# ========================================
# Generate secret key
# Run all the commands of target 'secretkey' in a single shell
.ONESHELL: secretkey
# Do not print the command names to STDOUT
.SILENT: secretkey
# This target does not generate a file
.PHONY: secretkey
# Use the current virtual environment Python shell
secretkey: SHELL = $(PYTHON)
secretkey:
from django.core.management.utils import get_random_secret_key
print(get_random_secret_key())
# Catch-all target for manage.py script
# =====================================
# Default rule to call 'manage.py' script
.DEFAULT:
@$(PYTHON) manage.py "$@"
# Final thoughts
# ==============
# - make is very powerful and has a steep learning curve, so it is advised
# to read its manual: https://www.gnu.org/software/make/manual.
# - Or not, just use tox, nox or pyinvoke.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment