Additional Basic Settings to Dockerized Django project with Cookiecutter

In previous post, I started a django project with cookiecutter. Then, I added poetry and ruff to the project. In this post, I will add more settings/configurations for the project, so I can use this as my template for other projects.

Prerequisite

Makefile

First thing I want to add is makefile. We can create a file to use as scripts, but I think makefile will be much easier to run the commands on console. The main reason of this is docker and poetry. Docker, docker-compose and poetry commands are quite complicated for me, so I will put all the commands into make file to make the commands easy. Create a file named makefile in root directory.

SHELL=/bin/bash

start: ## Start the docker containers
	@echo "Starting the docker containers"
	@docker-compose -f local.yml up
	@echo "Containers started - http://localhost:8000"
up: start # alias for start

poetry-export:
	@echo "Exporting poetry requirements to requirements/local.txt"
	@poetry export --without-hashes --with dev -f requirements.txt -o requirements/local.txt
	@echo "Exporting poetry requirements to requirements/base.txt"
	@poetry export --without-hashes -f requirements.txt -o requirements/base.txt
	@echo "Exporting poetry requirements to requirements/production.txt"
	@poetry export --without-hashes --with prod -f requirements.txt -o requirements/production.txt

stop: ## Stop Containers
	@docker-compose -f local.yml down --remove-orphans

build: stop ## Build Containers
	@docker-compose -f local.yml build

build-new: poetry-export stop ## Build Containers
	@docker-compose -f local.yml build --no-cache --pull

migrations: ## Create DB migrations in the container
	@docker-compose -f local.yml run --rm --user="$(id -u):$(id -g)" django python manage.py makemigrations

migrate: ## Run DB migrations in the container, optionally with app and migration as `make app=<app> migration=<migration_file_without_.py> migrate`
	@docker-compose -f local.yml run --rm --user="$(id -u):$(id -g)" django python manage.py migrate $(app) $(migration)

Script files

The makefile sometimes does not take the variable as I expected. I couldn’t find out the correct way to pass the variable. In this case, we can make the script file to work around. I made manage and runtests script files in root directory.

###runtests
#!/usr/bin/env bash

docker-compose -f local.yml run --rm django coverage run -m pytest "$@" && ruff .


###manage
#!/usr/bin/env bash

docker-compose -f local.yml run --rm --user="$(id -u):$(id -g)" django python -Wd manage.py "$@"

After create the script file, I tried to run them. and I got error permission denied. You can run ls -la on your bash and see if the script files have execute permission or not.

r = read, w = write, x = execute. I don’t have permission to execute the file. How do I change or add permission?

chmod +rwx <file_or_directory_name>

In this case, I already have read and write permission, so I could use just

chmod +x runtests
chmod +x manage

pytest.ini

Create new file named pytest.ini in root directory. I won’t explain all the details, but just copy the file content here. But you can refer to the pytest documentation for configuration and options to see what they are doing.

 [pytest]
addopts = --ds=config.settings.test
          --reuse-db
          -s

python_files = tests.py test_*.py
norecursedirs =
    .*
    compose
    dist
    docs
    htmlcov
    locale
    node_modules
    requirements
    static
    staticfiles
    templates

markers =
    admin
    core
    template_tags
    templates
    users
    urls
    widgets

VSCode Workspace Settings

You can configure the vscode settings globally. That’s what I used to do that. However, when working with teams, it is better to have the same workspace settings. Hit ctrl+shift+p and type workspace settings to open up the settings.json file.

Then, copy paste below settings.

{
  "files.associations": {
    "*.html": "django-html",
    "*.css": "tailwindcss"
  },
  "[python]": {
    "editor.defaultFormatter": "ms-python.black-formatter"
  },
  "[html][django-html][handlebars][hbs][mustache][jinja][jinja-html][nj][njk][nunjucks][twig]": {
    "editor.defaultFormatter": "monosans.djlint"
  },
  "editor.formatOnSave": true,
  "djlint.formatCss": true,
  "djlint.formatJs": false,
  "djlint.closeVoidTags": true,
  "djlint.formatAttributeTemplateTags": true,
  "djlint.profile": "django",
  "html.format.enable": true,
  "html.format.templating": true,
  "ruff.lint.args": ["\"args\": [\"--config=pyproject.toml\"]"],
}

We haven’t covered the tailwindcss in this series, so you can remove tailwindcss settings if you don’t like to use tailwind.