Awesome
django-pyproject
Description
This package allows you to store some/all of your settings in your pyproject.toml file (or any toml file in general).
Installation
You can add django-pyproject to your poetry project with:
poetry add django-pyproject
Or through pip:
pip install django-pyproject
Usage
You can use django-pyproject to import any settings specified in your pyproject file under [tool.django].
Settings file
To import django settings from your pyproject file, use this in your settings file:
from djpp import pyproject
pyproject.load()
This will work only if you have a standard django project structure.
If your pyproject file is located somewhere else or has a different name, you can specify it:
pyproject.load('path-to-your-pyproject-file')
PyProject file
All django settings in pyproject.toml file should be stored under [tool.django] key, like this:
[tool.django]
ALLOWED_HOSTS = []
You don't have to use uppercase letters for the variable names, django-pyproject will automatically convert them all. This does not work for dict key names:
[tool.django]
allowed_hosts = []
[tool.django.databases.default]
engine = 'django.db.backends.sqlite3'
HOST = '127.0.0.1'
PORT = '5432'
Will convert into:
ALLOWED_HOSTS = []
DATABASES = {
'default': {
'engine': 'django.db.backends.sqlite3',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
But what to do about relative filepaths, that you had to construct with os.path?
You can specify filepaths separating them with '/' in inline dict under key 'path'.
Using '..' will make django-pyproject go up a level.
Starting with '.' will make a path relative:
base_dir = { path = "." }
project_dir = { path = "./your_project_folder" }
repo_dir = { path = "./.." }
This will have the same effect as the following code in settings.py:
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
REPO_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
This is assuming you have a standard django project structure.
If a value needs to be taken from an environment, use inline dict with key 'path' and optional key 'default':
email_host_password = { env = 'SECRET_PASSWORD' }
secret_key = { env = 'SECRET_KEY', default = 'hello' }
Development, Docker & Production
If some of you settings have an alternative value for when DEBUG is off, specify them in [tool.django.production]. They will override regular settings if DEBUG is off.
Similarly, settings under [tool.django.development] will work only if DEBUG i on.
It is important to note, that DEBUG is True by default.
By default, django-pyproject applies production settings and sets DEBUG to False, if current evironment has a DJANGO_ENV variable, set to 'production'.
You can override it with your own key and value like this:
pyproject.load(production_env=('YOUR_KEY', 'your_value'))
If some of you settings have an alternative value for when the app is in container, specify them in [tool.django.docker]. They will override regular settings and development settings, and will be overriden by production settings.
By default, django-pyproject applies docker settings, if current evironment has a DJANGO_ENV variable.
You can override it with your own key like this:
pyproject.load(docker_env='YOUR_KEY')
Concatenating & Poetry keys
You can concat strings using inline dict with 'con' and 'cat' keys.
Additionally, you can access values in keys from [tool.poetry] using 'poetry' key.
This example explains both features:
[tool.poetry]
name = "my-app"
[tool.django]
project_name = { con = { poetry = "name" }, cat = ", v.1" }
will result in
PROJECT_NAME = 'my-app, v.1'
Keep in mind, that due to toml python library limitations, enclosing too much inline dicts in each other may result in error.
To overcome this, use con-poetry, con-poetry-cat and poetry-cat hybrids:
[tool.poetry]
name = "my-app"
[tool.django]
var1 = { con = "Hi! ", poetry = "name" }
var2 = { poetry = "name", cat = ", v.1" }
var3 = { con = "Hi! ", poetry = "name", cat = ", v.1" }
will result in
VAR1 = 'Hi! my-app'
VAR2 = 'my-app, v.1'
VAR3 = 'Hi! my-app, v.1'
Apps
You can group settings that belong to an external app together for easier access.
To do that, you can list them under [tool.django.apps.your_app].
You can also modify variables like INSTALLED_APPS from here with 'insert' key.
Here's an example for corsheaders:
[tool.django.apps.cors]
CORS_ORIGIN_WHITELIST = ['http://localhost:3000',]
CORS_ALLOW_CREDENTIALS = true
CSRF_COOKIE_NAME = "XCSRF-Token"
INSTALLED_APPS = { insert = 'corsheaders' }
MIDDLEWARE = { insert = 'corsheaders.middleware.CorsMiddleware', pos = 3 }
This is similar to the following python code:
CORS_ORIGIN_WHITELIST = ('http://localhost:3000',)
CORS_ALLOW_CREDENTIALS = True
CSRF_COOKIE_NAME = "XCSRF-Token"
INSTALLED_APPS.append('corsheaders')
MIDDLEWARE.insert(3, 'corsheaders.middleware.CorsMiddleware')
Full import
You also can simply import pyproject file (or any toml file) contents as a dict with load_all().