Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# See https://nens-meta.readthedocs.io/en/latest/config-files.html
default_language_version:
python: python3
exclude: ^{{
exclude: ^(django/)?{{

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
Expand Down
2 changes: 1 addition & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
## 0.9 (unreleased)


- Nothing changed yet.
- Updated django directory with changes from a recent project.


## 0.8 (2025-09-16)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# N&S python project/library cookiecutter template
# N&S python/django project cookiecutter template

Template for [cookiecutter](https://cookiecutter.readthedocs.io) so that
you can create a fresh plain python project or library.
Expand All @@ -14,7 +14,7 @@ Run the following command and answer the questions:

$ cookiecutter https://github.com/nens/cookiecutter-python-template

This cookiecutter can also generate a django project for you:
This cookiecutter can also generate a **django** project for you:

$ cookiecutter --directory django https://github.com/nens/cookiecutter-python-template

Expand Down
27 changes: 27 additions & 0 deletions django/{{ cookiecutter.project_name }}/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM python:3.13

# Install GDAL dependencies
RUN apt-get update && apt-get install -y \
libgdal-dev \
libsqlite3-mod-spatialite
# Set the environment variables for GDAL
ENV CPLUS_INCLUDE_PATH=/usr/include/gdal
ENV C_INCLUDE_PATH=/usr/include/gdal

# uv installation
COPY --from=ghcr.io/astral-sh/uv:0.8.17 /uv /usr/local/bin/uv
ENV UV_LINK_MODE=copy \
UV_PYTHON_DOWNLOADS=never \
UV_PYTHON=python3.13

WORKDIR /code
COPY pyproject.toml uv.lock /code/
RUN uv sync --no-install-project

# We only need to copy the src/ dir. This ensures the /code/staticfiles (filled below)
# is totally left alone.
COPY src src
RUN uv sync
ENV PATH="/code/.venv/bin:$PATH"

RUN python src/manage.py collectstatic --noinput --clear
61 changes: 61 additions & 0 deletions django/{{ cookiecutter.project_name }}/ansible/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Goal: do the day-to-day deployment of the site. This is done as the
# 'buildout' user, not as root. At least, we're going to try to do it like
# this. You need to have an ssh key configured to log in with: this is handled
# in the provision.yml playbook.

---
- name: Deploy new version of the project setup to the server
hosts: web
remote_user: buildout
tasks:

- name: Checkout correct version from github
ansible.builtin.git:
accept_hostkey: true
dest: {% raw %}/srv/{{ site_name }}{% endraw %}
repo: ssh://git@github.com/nens/{{ cookiecutter.project_name }}.git{% raw %}
version: "{{ checkout_name }}"

- name: Link server docker-compose file
ansible.builtin.file:
state: link
src: /srv/{{ site_name }}/docker-compose.server.yml
dest: /srv/{{ site_name }}/docker-compose.yml
# docker-compose files aren't included in the cookiecutter template.
# Look at (for instance) the "climatescan" project.

- name: Grab github docker token from server
ansible.builtin.command: # noqa: no-changed-when
cmd: "cat ~/.github-docker-pull-token.txt"
register: token

- name: Log into github package repo
community.docker.docker_login:
registry: ghcr.io
username: nensbuildout
password: "{{ token.stdout }}"

- name: Build our own docker
ansible.builtin.shell: # noqa: command-instead-of-shell no-changed-when
cmd: "docker-compose build"
chdir: /srv/{{ site_name }}

- name: Pull dockers
ansible.builtin.shell: # noqa: command-instead-of-shell no-changed-when
cmd: "docker-compose pull"
chdir: /srv/{{ site_name }}

- name: Stop dockers
ansible.builtin.shell: # noqa: command-instead-of-shell no-changed-when
cmd: "docker-compose down"
chdir: /srv/{{ site_name }}

- name: Start/update dockers
ansible.builtin.shell: # noqa: command-instead-of-shell no-changed-when
cmd: "docker-compose up -d"
chdir: /srv/{{ site_name }}

- name: Run migrate
ansible.builtin.command: # noqa: no-changed-when
cmd: "docker-compose run --rm web python src/manage.py migrate --noinput"
chdir: /srv/{{ site_name }}{% endraw %}
6 changes: 6 additions & 0 deletions django/{{ cookiecutter.project_name }}/ansible/inventory.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[web]
YOUR-SERVER

[web:vars]
site_name=TODO.lizard.net
checkout_name="main"
37 changes: 37 additions & 0 deletions django/{{ cookiecutter.project_name }}/ansible/provision.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
- name: Provision server to prepare for the actual deployment
hosts: web
remote_user: provisioner
become: true
tasks:

- name: Install various packages
ansible.builtin.apt:
name:
- docker.io
- docker-compose
state: present

- name: Add user 'buildout' and disable its password
ansible.builtin.user:
name: buildout
password: '*'
state: present
shell: "/bin/bash"
groups: docker

- name: Add maintainers' ssh keys so they can log in as user buildout.
ansible.posix.authorized_key:
user: buildout
key: {% raw %}https://github.com/{{ item }}.keys{% endraw %}
with_items:
- reinout
# TODO: add more maintainers

- name: Create dir inside /srv for the checkout
ansible.builtin.file:
path: {% raw %}/srv/{{ site_name }}{% endraw %}
state: directory
mode: "0755"
owner: buildout
group: buildout
74 changes: 41 additions & 33 deletions django/{{ cookiecutter.project_name }}/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,43 +1,56 @@
# See https://nens-meta.readthedocs.io/en/latest/config-files.html
[build-system]
requires = ["setuptools>=80", "setuptools-scm>=8"]
build-backend = "setuptools.build_meta"

[project]
name = "{{cookiecutter.project_name}}"
version = "0.1.dev0"
description = "{{cookiecutter.project_short_description}}"
authors = [
{name = "Nelen & Schuurmans", email = "info@nelen-schuurmans.nl"},
]
readme = "README.md"
requires-python = ">=3.12"
license = "MIT"
authors = [
{ name = "Nelen & Schuurmans", email = "info@nelen-schuurmans.nl" },
]
keywords = []
# Get classifier strings from http://www.python.org/pypi?%3Aaction=list_classifiers
classifiers = ["Programming Language :: Python"]
keywords = []
requires-python = ">=3.12"
dependencies = [
"django-types>=0.22.0",
"django==5.2.*",
"djangorestframework-gis>=1.2.0",
"djangorestframework-types>=0.9.0",
"djangorestframework>=3.16.1",
"nens-auth-client>=1.6.1",
"psycopg2-binary>=2.9.10",
"whitenoise>=6.10.0",
"django==5.2.*",
"django-types>=0.22.0",
"djangorestframework>=3.16.1",
"djangorestframework-dataclasses>=1.4.0",
"djangorestframework-gis>=1.2.0",
"djangorestframework-types>=0.9.0",
"drf-spectacular[sidecar]>=0.28.0",
# "gdal==3.8.4", # 3.8.4 is the version in 24.04. Works with newer libs.
"psycopg2-binary>=2.9.10",
"sentry-sdk[django]>=2.38.0",
"whitenoise>=6.10.0",
]

[project.urls]
homepage = "https://github.com/nens/{{ cookiecutter.project_name }}"

[tool.pytest.ini_options]
addopts = "--cov --cov-fail-under=80"
[dependency-groups]
dev = [
"pytest>=8.4.2",
"pytest-cov>=6.3.0",
"pytest-django>=4.11",
"pytest-sugar>=1.1.1"
]

[[tool.uv.index]]
url = "https://packages.lizard.net/"
# See https://nens-meta.readthedocs.io/en/latest/config-files.html
[build-system]
requires = ["setuptools>=80", "setuptools-scm>=8"]
build-backend = "setuptools.build_meta"

[tool.zest-releaser]
release = false
[tool.pyright]
# Pyright/pylance/vscode configuration.
# Note: if you want a different setup, you can overwrite this with a
# "pyrightconfig.json", which takes precedence.
include = "src"
venvPath = "."
venv = ".venv"

[tool.pytest.ini_options]
addopts = "--cov --cov-fail-under=80"

[tool.ruff]
# See https://docs.astral.sh/ruff/configuration/ for defaults.
Expand All @@ -50,13 +63,8 @@ select = ["E4", "E7", "E9", "F", "I", "UP", "C901"]
[tool.ruff.lint.isort]
known-first-party = ["{{ cookiecutter.package_name }}"]

[tool.pyright]
# Pyright/pylance/vscode configuration.
# Note: if you want a different setup, you can overwrite this with a
# "pyrightconfig.json", which takes precedence.
include = "src"
venvPath = "."
venv = ".venv"
[[tool.uv.index]]
url = "https://packages.lizard.net/"

[dependency-groups]
dev = ["pytest>=8.4.2", "pytest-cov>=6.3.0", "pytest-sugar>=1.1.1", "pytest-django>=4.11"]
[tool.zest-releaser]
release = false
Loading