A simple django project template that I believe is a good starting point for a project that is a small/medium internal tools (e.g a dashboard used by your department). This template includes:
- boilerplate for django password authentication
- boilerplate for configuring django error pages
- boilerplate for django-jazzmin configuration
- Github Actions for running tests using pytest, type checking using mypy, linting with ruff checking whether the program's version was bumped
- a starting point for the UI
- a Docker image definition that runs the application via bjoern
- most of [django settings](https://docs.djangoproject.com/en/{{ docs_version }}/ref/settings/) you'd like to define via environment variables exposed
- Whitenoise for django configured
- sqlite configured such that the datestimes are stored in the correct timezone
- useful django system checks
I believe that it's best to fork this repository and modify the template slightly to your liking. You can also use this repository as a template as such:
PROJECT_NAME="<INSERT YOUR PROJECT NAME HERE>"
PROJECT_DESCRIPTION="<INSERT A SHORT PROJECT DESCRIPTION HERE>"
MAINTAINER_EMAIL="<INSERT THE PROJECT'S MAINTAINER EMAIL HERE>"
COMPANY_DOMAIN="<INSERT THE EMAIL DOMAIN OF YOUR COMPANY HERE>"
COMPANY_NAME="<INSERT YOUR COMPANY NAME HERE>"
python -m venv venv \
&& source venv/bin/activate \
&& pip install django django-jazzmin whitenoise pytest pytest-django pytest-xdist coverage mypy django-stubs ruff bjoern \
&& pip freeze > requirements.txt
django-admin startproject --template "https://github.com/jacadzaca/django-robust-template/archive/refs/heads/master.zip" --name "Dockerfile" --name "pyproject.toml" --name "CHANGELOG.md" --exclude ".git" --name "README.md" "${PROJECT_NAME}" .
sed -ie "s/{{ project_name }}/$PROJECT_NAME/g" .github/workflows/check_version_bumped.yml
sed -ie "s/{{ project_name }}/$PROJECT_NAME/g" .github/workflows/check_enviroment_variables_included_in_readme.yml
sed -ie "s/Your application's description/$PROJECT_DESCRIPTION/g" Dockerfile
sed -ie "s/Your company/$COMPANY_NAME/g" Dockerfile
sed -ie "s/your.email@example.com/$MAINTAINER_EMAIL/g" Dockerfile
sed -ie "s/project_name/$PROJECT_NAME/g" templates/base.html
sed -ie "s/your.name@example.com/MAINTAINER_EMAIL/g" $PROJECT_NAME/settings.py
sed -ie "s/example.com/COMPANY_DOMAIN/g" $PROJECT_NAME/settings.py
or using PowerShell:
$PROJECT_NAME = "<INSERT YOUR PROJECT NAME HERE>"
$PROJECT_DESCRIPTION = "<INSERT A SHORT PROJECT DESCRIPTION HERE>"
$MAINTAINER_EMAIL = "<INSERT THE PROJECT'S MAINTAINER EMAIL HERE>"
$COMPANY_DOMAIN = "<INSERT THE EMAIL DOMAIN OF YOUR COMPANY HERE>"
$COMPANY_NAME = "<INSERT YOUR COMPANY NAME HERE>"
python -m venv venv
& "venv/Scripts/Activate.ps1"
pip install django django-jazzmin whitenoise pytest pytest-django pytest-xdist coverage mypy django-stubs ruff bjoern
pip freeze > requirements.txt
django-admin startproject --template "https://github.com/jacadzaca/django-robust-template/archive/refs/heads/master.zip" `
--name "Dockerfile" `
--name "pyproject.toml" `
--name "CHANGELOG.md" `
--name "README.md" `
--exclude ".git" `
$PROJECT_NAME .
(gc ".github/workflows/check_version_bumped.yml") -replace "{{ project_name }}", $PROJECT_NAME | Set-Content ".github/workflows/check_version_bumped.yml"
(gc "Dockerfile") -replace "Your application's description", $PROJECT_DESCRIPTION `
-replace "Your company", $COMPANY_NAME `
-replace "your.email@example.com", $MAINTAINER_EMAIL | Set-Content "Dockerfile"
(gc "templates/base.html") -replace "project_name", $PROJECT_NAME | Set-Content "templates/base.html"
(gc "$PROJECT_NAME/settings.py") -replace "your.name@example.com", $MAINTAINER_EMAIL `
-replace "example.com", $COMPANY_DOMAIN | Set-Content "$PROJECT_NAME/settings.py"
Variable name | Goal | What happens if empty? | Default value |
---|---|---|---|
SECRET_KEY | signing sessions, cookies etc | the application is started in DEBUG mode with a default key | openssl rand -base64 30 |
PORT | port on which the application is to listen | default value is used | 8080 |
DOMAIN | easy including of images, links etc. in the emails | default value is used | 127.0.0.1:{PORT} |
TZ | specifying the applications timezone | UTC |
|
EMAIL_USE_TLS | specifying whether to send emails using TLS | default value is used | False |
EMAIL_HOST | specifying the host of the SMTP server’s | emails are stored in files instead of being sent | N/A |
EMAIL_PORT | specifying the SMTP server’s port | default value is used | 26 |
EMAIL_HOST_USER | specifying the SMTP server user | default value is used | N/A |
EMAIL_HOST_PASSWORD | specifying the SMTP server user’s password | default value is used | N/A |
DEFAULT_FROM_EMAIL | specifying the default email from which the application sends message | default value is used | {{ project_name|title }}Bot <{{ project_name }}@domain.com |
SERVER_EMAIL | specifying the default email from which the applications send emails with errors | default value is used | {{ project_name|title }}Errors <{{ project_name }}@domain.com |
DJANGO_LOCALE | specifying the applications language | default value is used | en-us |
USE_THOUSAND_SEPARATOR | specifying whether to use a thousand separator | default value is used | True |
STATIC_ROOT | specifying the folder with static files when DEBUG is False | default value is used | /var/www/{{ project_name }}/static |
django_robust_template.J001
- emits an error if a first-party model dose not specifyverbose_name
. This is so the field's name is nicely displeyd when rendering forms, in admin etc.django_robust_template.J002
- emits an error if a first-party model field's does not specifydb_comment
. This is so each field is somewhat documenteddjango_robust_template.J003
- emits an error if a first-party model's field does not explicitly specifynull
argument. This is since explicit is better than implicitdjango_robust_template.J004
- emits an error if a first-party model's field does not explicitly specifyblank
argument. This is since explicit is better than implicitdjango_robust_template.J005
- emits a warning if a first-party model's CharField does not explicitly. specifymax_length
argument. This is since explicit is better than implicitdjango_robust_template.J006
- emits a warning if a first-party model's fielddb_comment
argument contains non-ascii characters. This is since some databases might throw odd errors if the comment contains non-ascii text.django_robust_template.J007
- emits a warning if a first-party model'sBooleanField
dose not explicitly define thedefault
argment. This is since aBooleanField
by [default allows None which is probably not desired](https://docs.djangoproject.com/en/{{ docs_version }}/ref/models/fields/#booleanfield) and since explicit is better than implicitdjango_robust_template.J008
- emits a warning if a first-party models's field specfies adefault
argument but not the [db_default
](https://docs.djangoproject.com/en/{{ docs_version }}/ref/models/fields/#db-default) argument. This is since if the database is ETL outside of django context, we'd like the default value to also be present.django_robust_template.J009
- emits an error if a first-party model's ForeingKey or ManyToManyField dose not explicitly specify therelated_name
argument. This is since explicit is better than implicitdjango_robust_template.J010
- emits an error if a first-party model's ForeingKey or ManyToManyField dose not explicitly specify therelated_query_name
argument. This is since explicit is better than implicitdjango_robust_template.J011
- emits an error if a first-party model has no explicitly defiendMeta
. This is since explicit is better than implicitdjango_robust_template.J012
- emits a warning if a first-party model's field dose not specifyhelp_text
argument. This is since I belive that most form fields become easier to understand withhelp_text
.django_robust_template.J013
- emits an error if a first-party model has no explicitly specifiededitable
argument. This is since by default,editable=True
and explicit is better than implicit.django_robust_template.J014
- emits an error if a first-party model dose not explicitly specifyverbose_name
in itsMeta
. This is to provide better interoperability (working as expected, out of the box) with admin etc. and since explicit is better than implicit and [django sets a defuaultverbose_name
](https://docs.djangoproject.com/en/{{ docs_version }}/ref/models/options/#verbose-name).django_robust_template.J015
- emits an error if a first-party model has no explicitly specifiedverbose_name_plural
in itsMeta
. This is to provide better interoperability with admin etc. and since explicit is better than implicit and [django sets a defaultverbose_name_plural
](https://docs.djangoproject.com/en/{{ docs_version }}/ref/models/options/#verbose-name-plural)django_robust_template.J016
- emits an error if a first-party model has nodb_table_comment
specified in its Meta. This is so each table is somehow documented.django_robust_template.J017
- emits a warning if a first-party model'sdb_table_comment
is non-ascii. This is since some databases might throw odd errirs if the comment contains non-ascii text.django_robust_template.J018
- emits an error if a first-party models has nodb_table
specified in itsMeta
. This is so to ensure all of the tables used by the django follow a naming convention (e.g. are prefixed with the program's name).django_robust_template.J019
- emits an error if a first-party model's ManyToManyField dose not explicitly specify thedb_table
argument. This is to ensure tables used by the program follow a naming convetion and since explicit is better than implicitdjango_robust_template.J020
- emits an error if a first-party model has notdefault_permissions
specified in itsMeta
. This is so to ensure the table with permissions isn't needlesl cluttered [(django creates some permission by default)](https://docs.djangoproject.com/en/{{ docs_version }}/ref/models/options/#default-permissions) and since explicit is better than implicitdjango_robust_template.J021
- emits a warning if a first-party model does not contain a field namedlast_modified_at
. This is since I consider such field useful to have on all models.django_robust_template.J022
- emits a warning if a first-party model dose not explicitly specify a__str__
method. This is since explicit is better than implicit and to ensure better interoperability with admin etc.django_robust_template.J023
- emits a warning if a first-party mdoel does not explicitly specify a__repr__
method. This is since I conside such method useful for debugging.django_robust_template.J024
- emits a warning if a first-party model does not specify aget_absoulte_url
method. This is to improve interoperability with django.
Please keep in mind that using this specific set of checks is highly subjective -- if you feel like
any of the is stupid, you can to remove any of the from checks.py
or disable any of them by specifying
SILENCED_SYSTEM_CHECKS
in your settings.py
, e.g:
SILENCED_SYSTEM_CHECKS = [
'models.J019',
]