Skip to content

Local application development environment


This document describes our "new-style" developer environment. If your project has a file present in the root, look at the original documentation.

This page lists common tasks which a developer may want to perform when working with our standard webapp developer environment. Read more about the philosophy behind the design of this environment in our explainer guide.

Unless otherwise stated, commands in this guide should be run from the project's root directory.

If you have poe installed to your PATH then commands of the form poetry poe ... can be shortened to poe ....


Make sure that you have docker, docker compose, poetry and poe installed. Instructions for this can be found in the guide on how-to prepare your system.

Install application dependencies via:

poetry install

All poe tasks and a brief description can be shown via:

poetry poe

Standard endpoints

When running the application in production or development mode, the following endpoints will usually be present:

  • The application itself at http://localhost:8000/.
  • A PostgreSQL instance at localhost:5432.
  • For applications which host an API behind the API Gateway:

Running the application


To spin up a local database, run migrations and start the application in debug mode:

poetry poe up

To spin up a local database, run migrations and start the application from the production container:

poetry poe up:production

Press Ctrl-C to stop the application.


To run the application in the background, waiting for application startup before returning control:

poetry poe up --wait

Similarly, for the production application:

poetry poe up:production --wait

When running in the background, logs can be streamed from the webapp via:

docker compose logs --follow webapp

Similarly, for the production application:

docker compose logs --follow webapp-production


To make sure that the application is stopped but keeping the local database's contents:

poetry poe down

To make sure that the application is stopped, delete any local database contents and remove any containers which may still be running:

poetry poe down:hard

Pulling and rebuilding containers

To build or rebuild all container images used by the application:

poetry poe compose:build

To build or rebuild all container images used by the application and pull any new base images:

poetry poe compose:build --pull

To pull any images used by the docker compose configuration:

poetry poe compose:pull

Django management commands

To run Django management commands:

poetry poe manage {command}

To run a database migration:

poetry poe manage migrate

To create a new super-user which can sign in to the admin UI:

poetry poe manage createsuperuser

To create new migrations after a change of model:

poetry poe manage makemigrations {app} -n "{human_friendly_name_of_migration}"
On Linux machines the generated files are owned by root.

The resulting migrations will be owned by "root" on Linux systems. You may want to change ownership after creation by running sudo chown -R "$USER" . in the repository root.

To launch an interactive Python shell pre-configured to be able to use database models:

poetry poe manage shell
This shell runs inside the container and so files you create will be owned by "root".

You can change ownership of any files after creation by running sudo chown -R "$USER" . in the repository root.

Test suites and code linting

To run pre-commit checks in order to fix up code style and layout to match our common convention:

poetry poe fix

To run the Python test suite via tox:

poetry poe tox


The tox poe task runs tox in a container which is close to the production container. On Apple Silicon machines, this means that the tests may run in x86 emulation and will probably be slower than running them "natively". On the flip side, this means that the tests are running in an environment which better matches the one the code will ultimately run in.

To run the Python test suite via tox using the locally installed version of Python:

poetry poe tox:local

To run the Python test suite directly via pytest:

poetry poe pytest:local

Some IDEs, such as VSCode, will run pytest directly like this rather than running tox and so it's important to check that doing so still works.


The tox:local and pytest:local tasks are very similar. Running tests in tox arranges for code coverage and test reports to be generated which are used in CI. The HTML code coverage report is also useful for tracking down which lines are not being covered by tests.

Both tox and tox:local can take additional arguments which are passed to tox. Use this to, for example, only run tests within a single file:

poetry poe tox -e py3 -- path/to/



If you add a new dependency to the application as described below you will need to stop and re-start the application via poetry poe up for the dependencies to be installed within the application container.

If you are running the application via docker compose up, you'll need to either add the --build option or use docker compose build to re-build the containers.

To add a new dependency for the application itself:

poetry add {dependency}

To add a new development-time dependency used only when the application is running locally in development or in testing:

poetry add -G dev {dependency}

To remove a dependency which is no longer needed:

poetry remove {dependency}

For example:

  • Django 4.2 is required to run the application at all. It was added via poetry add Django~=4.2.0.
  • The Django debug toolbar is required only when running locally in development. It was added via poetry add -G dev django-debug-toolbar.
  • The pytest library is only used when running tests. It was added via poetry poe add -G dev testing pytest.

Poetry-managed virtualenv

To run a command within the Python virtualenv managed by poetry, use poetry run. For example, the tox:local poe task could also be done via:

poetry run tox

To launch a command line shell inside the virtual environment:

poetry shell

To delete the automatically created Python virtual environment in order to save disk space:

poetry env remove python3