An opinionated boilerplate for your Django projects.
- Env Variables Manager: Django Environ
- Package manager: Poetry
- Database: PostgreSQL
- Task Queue: Celery with Redis
- Testing: PyTest
- Logging: Sentry
- Python Code Formatter: Black
- Static File Storage: AWS S3 or Digital Ocean Spaces
- Dev Orchestration: Docker & Docker Compose
- Static File Compiler: Webpack
- JS lint: ESLint
- Style lint: Stylelint
This is a guide on how to use this repo and save hours of boring configuration.
Instead of running django-admin startproject to start your new project, clone this repo in a directory of your choosing
git clone [email protected]:fceruti/django-starter-project.git <new-directory>
At this point you may either
- Start a clean git repo by removing the .gitdirectory and then runninggit init.
- Receive patches and updates of this repo by modifying .git/configand switch[remote "origin"]for[remote "upstream"], and then add your ownoriginby runninggit remote add origin <your_repo>.
Following the 12 Factor App Guide, we will configure our app by setting the configuration variables in the environment. To do that, just create a file named .env in the root of the project and django-environ will pick it up and populate our settings.
You may use the example file as a starting point:
cp .env.example .env
I'll call this database django_db for the purposes of this guide, but you can call it whatever you want. Just watch out for careless copy-pasting.
Now run
poetry run migrate
You have two choices, either you turn every service on your own or you use docker-compose
We need to override DATABASE_URL environment variable inside of the Docker containers to connect directly to your host machine. Create a file called .env.docker with the following content:
DATABASE_URL=postgres://<user>@host.docker.internal:5432/django_db
- user is the user on your host machine that has access to postgres in this case.
Now we are ready to start the project.
docker-compose up
Visit http://127.0.0.1:8000 and you'll see your site up and running π§ββοΈ
First of all, install pyenv so you can use the specified python version in .python-version file. Then, install poetry, which is a package manager replacement for pip. Now install all the project's dependencies with
poetry install
Make sure you have redis-server running and finally on 3 separate consoles run:
server
poetry run worker
worker
poetry run server
webpack
cd assets
npm install
npm run dev
Visit http://127.0.0.1:8000 and you'll see your site up and running π§ββοΈ
Here are a few commands that may come in handy
| Command | Description | 
|---|---|
| docker ps | List all containers (-a to include stopped) | 
| docker system df -v | Display a list of all images, containers and volumes | 
| docker logs --follow <container_id> | Display the logs of a container | 
| docker exec -it <container_id> /bin/bash | Attach into a running container | 
| docker run --rm <image_name> /bin/bash | Run a docker container based on an image and get a prompt | 
| docker-compose run --rm web /bin/bash | Same as before but for services defined in docker-compose.yml | 
| docker-compose run --rm web /bin/bash -c 'python manage.py migrate' | Run a management command | 
These shortcuts are at your disposal:
| Command | Shortcut for | 
|---|---|
| poetry run tests | poetry run pytest tests/ | 
| poetry run server | poetry run python manage.py runserver_plus | 
| poetry run worker | poetry run python manage.py celery_autoreload | 
| poetry run shell | poetry run python manage.py shell_plus | 
| poetry run makemigrations | poetry run python manage.py makemigrations | 
| poetry run migrate | poetry run python manage.py migrate | 
To compile your static files, you need to have npm installed and all the local dependencies (run npm install). Then can execute the following commands
| Command | Shortcut for | 
|---|---|
| npm run dev | webpack --mode development --env dev--watch | 
| npm run build_stg | webpack --mode production --env stg | 
| npm run build_prod | webpack --mode production --env prod | 
| npm run lint:js | eslint js/** --fix | 
| npm run lint:csss | stylelint scss/*.scss --syntax scss | 
These environment variables can be provided to configure your project.
| Name | Values | Default | Description | 
|---|---|---|---|
| ENV | dev, test, qa, prod | prod | Indicates in which environment the project is running on | 
| DEBUG | on, off | off | Run server in debug mode | 
| LANGUAGE_CODE | Language Identifier (RFC 3066) | en-US | List of language codes | 
| TIME_ZONE | Record of IANA time zone database | America/Santiago | List of timezones | 
| USE_I18N | on, off | on | Enable translation system | 
| USE_L10N | on, off | on | Enable localized formatting | 
| USE_TZ | on, off | on | Enable timezone aware dates in | 
| DEFAULT_FROM_EMAIL | E-mail address | -- | Email address from which transactional emails will be sent from | 
| EMAIL_BACKEND | Path to backend | django.core.mail.backends.smtp.EmailBackend | The backend to use for sending emails. List of backends | 
| SECRET_KEY | Random string | -- | Used to provide cryptographic signing | 
| ALLOWED_HOSTS | List of domains | -- | Represents the host/domain names that this site can serve. | 
| DJANGO_DATABASE_URL | Database url | -- | Describes the database connection with a url structure. | 
| LOGIN_URL | Url | /login/ | Url to redirect users when login is needed | 
| LOGIN_REDIRECT_URL | Url | / | Url to redirect users after login in | 
| STATIC_URL | Url | /static/ | Url from which static files are served | 
| MEDIA_URL | Url | /media/ | Url from which media files are served | 
| STATIC_ROOT | Directory path | ${project_root}/static | Directory where all static files will be collected to | 
| MEDIA_ROOT | Directory path | ${project_root}/media | Directory where all uploaded files will be stored | 
| LOGS_ROOT | Directory path | ${project_root}/logs | Directory where all logs will be stored | 
| Name | Values | Default | Description | 
|---|---|---|---|
| CELERY_BROKER_URL | Database url | -- | A common value for development is to use redis://cache, but it's recommended for production to use RabbitMQ | 
| CELERY_TASK_ALWAYS_EAGER | on, off | off | If this is True, all tasks will be executed locally by blocking until the task returns. | 
| Name | Values | Default | Description | 
|---|---|---|---|
| USE_S3_STATIC_STORAGE | on, off | off | Whether or not to use S3 | 
| AWS_ACCESS_KEY_ID | str | -- | AWS Access key id | 
| AWS_SECRET_ACCESS_KEY | str | -- | AWS Secret access key | 
| AWS_STORAGE_BUCKET_NAME | str | -- | Name of S3 bucket to be used | 
| Name | Values | Default | Description | 
|---|---|---|---|
| USE_DEBUG_TOOLBAR | on, off | off | Enables django debug toolbar | 
| Name | Values | Default | Description | 
|---|---|---|---|
| LOGS_ROOT | path | -- | Path to the directory where logs are to be stored | 
| USE_SENTRY | on, off | off | Enables sentry | 
| SENTRY_DSN | string | -- | Private URL-like configuration | 
Nowadays, my go-to editor is VSCode, so here's a template for .vscode/settings.json:
{
  // Editor
  "editor.formatOnSave": true,
  "files.exclude": {
    "**/__pycache__": true,
    "**/.pytest_cache": true,
    "**/*.egg-info": true
  },
  // Search
  "search.exclude": {
    "**/.git": true,
    "**/.vscode": true,
    "**/node_modules": true,
    "**/static": true,
    "**/media": true,
    "**/logs": true,
    "**/tmp": true,
    "**/locale": true
  },
  "search.showLineNumbers": true,
  // Python
  "python.venvPath": "<env_path>",
  "python.envFile": "${workspaceFolder}/.env",
  "python.jediEnabled": false,
  // Linting
  "python.linting.enabled": true,
  "python.linting.pylintEnabled": true,
  "python.linting.flake8Enabled": true,
  "python.formatting.provider": "black",
  "python.linting.pylintArgs": [
    "--load-plugins",
    "pylint_django",
    "--rcfile",
    "setup.cfg"
  ],
  // Eslint
  "eslint.options": {
    "configFile": ".eslintrc.json"
  },
  "eslint.nodePath": "assets/node_modules",
  "eslint.workingDirectories": ["assets/"],
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  // Stylelint
  "css.validate": false,
  "less.validate": false,
  "scss.validate": false
}
To fill the python.venvPath run poetry show -v to see the path to your virtual environment.