Defining the project structure

Right, let’s talk about organization. Before getting carried away with the actual coding – which inevitably brings its own set of challenges – it’s a good idea to plan where everything will go. A well-defined project structure acts as a map, helping to keep track of all the different parts and preventing things from getting lost later on.

Without a clear structure, a project can quickly become rather difficult to navigate. Finding specific files might turn into a frustrating exercise, maintenance becomes a chore, and you risk stumbling over bits of code you wrote weeks ago and no longer understand – perhaps even being metaphorically tripped up by a rogue semicolon. This sort of disarray, while perhaps character-building, is generally counterproductive when the goal is to create functional software without unnecessary hassle.

Therefore, what follows is an initial proposal for organising the Beryl project’s directories. It’s presented with the full understanding that reality often has other plans, but consider it a starting point – a gentle nudge towards organisation, hoping the codebase doesn’t immediately descend into an unmanageable tangle.

Choosing the right tools

To get started, we first need to manually install the core tooling that will help manage the project.

I’m going to use UV to manage this project. There are several alternatives; traditionally, working with Django often involves using pip and a venv (virtual environment) to manage dependencies effectively. However, uv aims to be a faster, unified replacement for tools like pip, pip-tools, poetry, and venv.

Given that this project aims to be reasonably modern and will eventually include several distinct parts (like the web application, mobile components, Docker configurations, and utility scripts), using a tool that can manage this complexity effectively makes sense. uv’s workspace feature is particularly helpful here.

There is a lot of advantages using uv, one is that I can set entire project from my existing GitHub repository, and add sub projects called here workspaces and use them separatelly for each of my components. Saying that - I would have different sets of libraries for webapp and different for mobile, and they would not collide.

It also uses requirements.txt and pyproject.toml files making it compatible with pip and poetry.

The structure of this project consists of following folders:

Project bootstrap

uv can be installed using snap:

$ sudo snap install --classic astral-uv

From now, I will operate exclusivelly in beryl3 directory, which in my case is a local github repository.

Prepare environment:

$ uv init \
  --name beryl3 \
  --bare \
  --no-package \
  --description "Beryl, collection management system" \
  --author-from git

Setup first component which is Web Application:

$ uv init \
  --name beryl3-webapp \
  --bare \
  --no-package \
  --description "Beryl, collection management system. Web application" \
  --author-from git \
  webapp/

Adding `beryl3-webapp` as member of workspace `/home/mdubiel/github/beryl3`
Initialized project `beryl3-webapp` at `/home/mdubiel/github/beryl3/webapp/`

Create addtional folders for docker components and scripts folder:

$ mkdir docker scripts

Now, the folder structure should look like this:

$ tree --dirsfirst -F
./
├── docker/
├── scripts/
├── webapp/
│   └── pyproject.toml
├── LICENSE
├── pyproject.toml
├── README.md
└── uv.lock

3 directories, 5 files

Let’s add necessary elements to that, we need python3.12 for entire project, and django for webapp component:

$ uv python install 3.12
Installed Python 3.12.10 in 1.75s
 + cpython-3.12.10-linux-x86_64-gnu

Set this python as default:

$ uv python pin 3.12
Pinned `.python-version` to `3.12`

Install django:

$ cd webapp/ && uv add "django>=5.2,<6.0"

Verify installation:

$ uv run django-admin --version
5.2

$ uv run python --version
Python 3.12.10

$ uv tree
Resolved 7 packages in 1ms
beryl3-webapp v0.1.0
└── django v5.2
    ├── asgiref v3.8.1
    └── sqlparse v0.5.3
beryl3 v0.1.0
└── beryl3-webapp v0.1.0 (*)
(*) Package tree already displayed

Next steps

The next step is to structure Django web application folder, what is explained in the next chapter.