mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-08-14 00:44:53 +03:00
Merge branch 'master' into django-stubs-mypy-compat
# Conflicts: # {{cookiecutter.project_slug}}/requirements/local.txt
This commit is contained in:
commit
d8462c4b18
9
.github/FUNDING.yml
vendored
9
.github/FUNDING.yml
vendored
|
@ -2,11 +2,4 @@
|
||||||
|
|
||||||
github: [pydanny, browniebroke]
|
github: [pydanny, browniebroke]
|
||||||
patreon: feldroy
|
patreon: feldroy
|
||||||
open_collective: # Replace with a single Open Collective username
|
open_collective: cookiecutter-django
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
|
||||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
||||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
||||||
liberapay: # Replace with a single Liberapay username
|
|
||||||
issuehunt: # Replace with a single IssueHunt username
|
|
||||||
otechie: # Replace with a single Otechie username
|
|
||||||
custom: ["https://www.patreon.com/browniebroke"]
|
|
||||||
|
|
2
.github/ISSUE_TEMPLATE/bug.md
vendored
2
.github/ISSUE_TEMPLATE/bug.md
vendored
|
@ -42,7 +42,7 @@ labels: bug
|
||||||
|
|
||||||
- Python version, run `python3 -V`:
|
- Python version, run `python3 -V`:
|
||||||
- Docker version (if using Docker), run `docker --version`:
|
- Docker version (if using Docker), run `docker --version`:
|
||||||
- docker-compose version (if using Docker), run `docker-compose --version`:
|
- docker compose version (if using Docker), run `docker compose --version`:
|
||||||
- ...
|
- ...
|
||||||
|
|
||||||
- Options selected and/or [replay file](https://cookiecutter.readthedocs.io/en/latest/advanced/replay.html):
|
- Options selected and/or [replay file](https://cookiecutter.readthedocs.io/en/latest/advanced/replay.html):
|
||||||
|
|
66
.github/contributors.json
vendored
66
.github/contributors.json
vendored
|
@ -53,6 +53,12 @@
|
||||||
"twitter_username": "sfdye",
|
"twitter_username": "sfdye",
|
||||||
"is_core": true
|
"is_core": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Jelmer Draaijer",
|
||||||
|
"github_login": "foarsitter",
|
||||||
|
"twitter_username": "",
|
||||||
|
"is_core": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "18",
|
"name": "18",
|
||||||
"github_login": "dezoito",
|
"github_login": "dezoito",
|
||||||
|
@ -553,11 +559,6 @@
|
||||||
"github_login": "jvanbrug",
|
"github_login": "jvanbrug",
|
||||||
"twitter_username": ""
|
"twitter_username": ""
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Jelmer Draaijer",
|
|
||||||
"github_login": "foarsitter",
|
|
||||||
"twitter_username": ""
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Jerome Caisip",
|
"name": "Jerome Caisip",
|
||||||
"github_login": "jeromecaisip",
|
"github_login": "jeromecaisip",
|
||||||
|
@ -1397,5 +1398,60 @@
|
||||||
"name": "Matheus Jardim Bernardes",
|
"name": "Matheus Jardim Bernardes",
|
||||||
"github_login": "matheusjardimb",
|
"github_login": "matheusjardimb",
|
||||||
"twitter_username": ""
|
"twitter_username": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "masavini",
|
||||||
|
"github_login": "masavini",
|
||||||
|
"twitter_username": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Joseph Hanna",
|
||||||
|
"github_login": "sanchimenea",
|
||||||
|
"twitter_username": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tmajerech",
|
||||||
|
"github_login": "tmajerech",
|
||||||
|
"twitter_username": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "villancikos",
|
||||||
|
"github_login": "villancikos",
|
||||||
|
"twitter_username": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Imran Rahman",
|
||||||
|
"github_login": "infraredCoding",
|
||||||
|
"twitter_username": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "hleroy",
|
||||||
|
"github_login": "hleroy",
|
||||||
|
"twitter_username": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Shayan Karimi",
|
||||||
|
"github_login": "shywn-mrk",
|
||||||
|
"twitter_username": "shywn_mrk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sadra Yahyapour",
|
||||||
|
"github_login": "lnxpy",
|
||||||
|
"twitter_username": "lnxpylnxpy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tharushan",
|
||||||
|
"github_login": "Tharushan",
|
||||||
|
"twitter_username": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fateme Fouladkar",
|
||||||
|
"github_login": "FatemeFouladkar",
|
||||||
|
"twitter_username": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "zhaoruibing",
|
||||||
|
"github_login": "zhaoruibing",
|
||||||
|
"twitter_username": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -17,20 +17,20 @@ repos:
|
||||||
- id: detect-private-key
|
- id: detect-private-key
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||||
rev: "v3.0.0-alpha.9-for-vscode"
|
rev: "v3.0.1"
|
||||||
hooks:
|
hooks:
|
||||||
- id: prettier
|
- id: prettier
|
||||||
args: ["--tab-width", "2"]
|
args: ["--tab-width", "2"]
|
||||||
|
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
rev: v3.4.0
|
rev: v3.10.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
args: [--py311-plus]
|
args: [--py311-plus]
|
||||||
exclude: hooks/
|
exclude: hooks/
|
||||||
|
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 23.3.0
|
rev: 23.7.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ repos:
|
||||||
- id: isort
|
- id: isort
|
||||||
|
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 6.0.0
|
rev: 6.1.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
|
|
||||||
|
|
357
CHANGELOG.md
357
CHANGELOG.md
|
@ -3,6 +3,363 @@ All enhancements and patches to Cookiecutter Django will be documented in this f
|
||||||
|
|
||||||
<!-- GENERATOR_PLACEHOLDER -->
|
<!-- GENERATOR_PLACEHOLDER -->
|
||||||
|
|
||||||
|
## 2023.08.10
|
||||||
|
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Corrected 'or' translation to pt-br ([#4507](https://github.com/cookiecutter/cookiecutter-django/pull/4507))
|
||||||
|
|
||||||
|
## 2023.08.04
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Auto-update pre-commit hooks ([#4503](https://github.com/cookiecutter/cookiecutter-django/pull/4503))
|
||||||
|
|
||||||
|
## 2023.08.01
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Auto-update pre-commit hooks ([#4499](https://github.com/cookiecutter/cookiecutter-django/pull/4499))
|
||||||
|
|
||||||
|
- Update django-anymail to 10.1 ([#4497](https://github.com/cookiecutter/cookiecutter-django/pull/4497))
|
||||||
|
|
||||||
|
- Update sentry-sdk to 1.29.2 ([#4496](https://github.com/cookiecutter/cookiecutter-django/pull/4496))
|
||||||
|
|
||||||
|
- Update django to 4.2.4 ([#4495](https://github.com/cookiecutter/cookiecutter-django/pull/4495))
|
||||||
|
|
||||||
|
- Update flake8 to 6.1.0 ([#4489](https://github.com/cookiecutter/cookiecutter-django/pull/4489))
|
||||||
|
|
||||||
|
- Update uvicorn to 0.23.2 ([#4490](https://github.com/cookiecutter/cookiecutter-django/pull/4490))
|
||||||
|
|
||||||
|
- Update sentry-sdk to 1.29.1 ([#4494](https://github.com/cookiecutter/cookiecutter-django/pull/4494))
|
||||||
|
|
||||||
|
## 2023.07.30
|
||||||
|
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix `README.md` file extension in `setup.py` ([#4488](https://github.com/cookiecutter/cookiecutter-django/pull/4488))
|
||||||
|
|
||||||
|
## 2023.07.28
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Add support for Drone CI ([#4382](https://github.com/cookiecutter/cookiecutter-django/pull/4382))
|
||||||
|
|
||||||
|
## 2023.07.27
|
||||||
|
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- Document that `docker exec` does not work for running management commands ([#4487](https://github.com/cookiecutter/cookiecutter-django/pull/4487))
|
||||||
|
|
||||||
|
- Add Webpack instructions for developping locally with HTTPS ([#4486](https://github.com/cookiecutter/cookiecutter-django/pull/4486))
|
||||||
|
|
||||||
|
## 2023.07.25
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Upgrade to traefik 2.10.4 ([#4483](https://github.com/cookiecutter/cookiecutter-django/pull/4483))
|
||||||
|
|
||||||
|
## 2023.07.24
|
||||||
|
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Add missing custom CRSF error page in prod ([#4464](https://github.com/cookiecutter/cookiecutter-django/pull/4464))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- Replace `docker-compose` by `docker compose` in docs ([#4463](https://github.com/cookiecutter/cookiecutter-django/pull/4463))
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update drf-spectacular to 0.26.4 ([#4481](https://github.com/cookiecutter/cookiecutter-django/pull/4481))
|
||||||
|
|
||||||
|
## 2023.07.20
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update djlint to 1.32.1 ([#4475](https://github.com/cookiecutter/cookiecutter-django/pull/4475))
|
||||||
|
|
||||||
|
## 2023.07.19
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update factory-boy to 3.3.0 ([#4472](https://github.com/cookiecutter/cookiecutter-django/pull/4472))
|
||||||
|
|
||||||
|
- Update gunicorn to 21.2.0 ([#4473](https://github.com/cookiecutter/cookiecutter-django/pull/4473))
|
||||||
|
|
||||||
|
- Update djlint to 1.32.0 ([#4471](https://github.com/cookiecutter/cookiecutter-django/pull/4471))
|
||||||
|
|
||||||
|
## 2023.07.18
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update gunicorn to 21.1.0 ([#4470](https://github.com/cookiecutter/cookiecutter-django/pull/4470))
|
||||||
|
|
||||||
|
- Update uvicorn to 0.23.1 ([#4468](https://github.com/cookiecutter/cookiecutter-django/pull/4468))
|
||||||
|
|
||||||
|
- Update gunicorn to 21.0.1 ([#4466](https://github.com/cookiecutter/cookiecutter-django/pull/4466))
|
||||||
|
|
||||||
|
## 2023.07.13
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update sentry-sdk to 1.28.1 ([#4458](https://github.com/cookiecutter/cookiecutter-django/pull/4458))
|
||||||
|
|
||||||
|
## 2023.07.11
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Improve type hints for `UserSerializer` ([#4429](https://github.com/cookiecutter/cookiecutter-django/pull/4429))
|
||||||
|
|
||||||
|
- [pre-commit.ci] pre-commit autoupdate ([#4453](https://github.com/cookiecutter/cookiecutter-django/pull/4453))
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix `/tmp` bind mount in devcontainer config ([#4455](https://github.com/cookiecutter/cookiecutter-django/pull/4455))
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update black to 23.7.0 ([#4452](https://github.com/cookiecutter/cookiecutter-django/pull/4452))
|
||||||
|
|
||||||
|
## 2023.07.10
|
||||||
|
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Prevent user's name being shown twice on user details page if username is set to email ([#4436](https://github.com/cookiecutter/cookiecutter-django/pull/4436))
|
||||||
|
|
||||||
|
- Add missing trailing space in `EMAIL_SUBJECT_PREFIX` setting ([#4434](https://github.com/cookiecutter/cookiecutter-django/pull/4434))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- Clarify documentation on which port to use to access the application when using Webpack or Gulp ([#4413](https://github.com/cookiecutter/cookiecutter-django/pull/4413))
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update django-coverage-plugin to 3.1.0 ([#4446](https://github.com/cookiecutter/cookiecutter-django/pull/4446))
|
||||||
|
|
||||||
|
- Update pillow to 10.0.0 ([#4432](https://github.com/cookiecutter/cookiecutter-django/pull/4432))
|
||||||
|
|
||||||
|
- Update django-cors-headers to 4.2.0 ([#4445](https://github.com/cookiecutter/cookiecutter-django/pull/4445))
|
||||||
|
|
||||||
|
- Update sentry-sdk to 1.28.0 ([#4444](https://github.com/cookiecutter/cookiecutter-django/pull/4444))
|
||||||
|
|
||||||
|
## 2023.07.09
|
||||||
|
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix missing run configurations when PyCharm is selected ([#4441](https://github.com/cookiecutter/cookiecutter-django/pull/4441))
|
||||||
|
|
||||||
|
## 2023.07.08
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update sentry-sdk to 1.27.1 ([#4440](https://github.com/cookiecutter/cookiecutter-django/pull/4440))
|
||||||
|
|
||||||
|
## 2023.07.04
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Add PostgreSQL 15 ([#4431](https://github.com/cookiecutter/cookiecutter-django/pull/4431))
|
||||||
|
|
||||||
|
- [pre-commit.ci] pre-commit autoupdate ([#4438](https://github.com/cookiecutter/cookiecutter-django/pull/4438))
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update sentry-sdk to 1.27.0 ([#4439](https://github.com/cookiecutter/cookiecutter-django/pull/4439))
|
||||||
|
|
||||||
|
- Update postcss-preset-env to 9.0.0 ([#4437](https://github.com/cookiecutter/cookiecutter-django/pull/4437))
|
||||||
|
|
||||||
|
## 2023.07.03
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Add a devcontainer configuration with Docker ([#4198](https://github.com/cookiecutter/cookiecutter-django/pull/4198))
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update django-stubs to 4.2.3 ([#4430](https://github.com/cookiecutter/cookiecutter-django/pull/4430))
|
||||||
|
|
||||||
|
- Update django to 4.2.3 ([#4435](https://github.com/cookiecutter/cookiecutter-django/pull/4435))
|
||||||
|
|
||||||
|
## 2023.06.30
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Add option to use django-allauth workflow in the admin ([#1921](https://github.com/cookiecutter/cookiecutter-django/pull/1921))
|
||||||
|
|
||||||
|
## 2023.06.29
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Replace psycopg2 by psycopg3 ([#4421](https://github.com/cookiecutter/cookiecutter-django/pull/4421))
|
||||||
|
|
||||||
|
## 2023.06.28
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Upgrade to django 4.2 ([#4393](https://github.com/cookiecutter/cookiecutter-django/pull/4393))
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix PostgreSQL version in GitHub workflow ([#4423](https://github.com/cookiecutter/cookiecutter-django/pull/4423))
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update werkzeug to 2.3.6 ([#4427](https://github.com/cookiecutter/cookiecutter-django/pull/4427))
|
||||||
|
|
||||||
|
- Update django-compressor to 4.4 ([#4422](https://github.com/cookiecutter/cookiecutter-django/pull/4422))
|
||||||
|
|
||||||
|
## 2023.06.27
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Populate User `name` field during social auth ([#3968](https://github.com/cookiecutter/cookiecutter-django/pull/3968))
|
||||||
|
|
||||||
|
- Add djLint for HTML formatting and linting ([#4389](https://github.com/cookiecutter/cookiecutter-django/pull/4389))
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Only include prettier pre-commit hook with node-based front-end pipeline ([#4418](https://github.com/cookiecutter/cookiecutter-django/pull/4418))
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update djangorestframework-stubs to 3.14.2 ([#4420](https://github.com/cookiecutter/cookiecutter-django/pull/4420))
|
||||||
|
|
||||||
|
- Update django-stubs to 4.2.2 ([#4419](https://github.com/cookiecutter/cookiecutter-django/pull/4419))
|
||||||
|
|
||||||
|
## 2023.06.26
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update pytest to 7.4.0 ([#4412](https://github.com/cookiecutter/cookiecutter-django/pull/4412))
|
||||||
|
|
||||||
|
- Update redis to 4.6.0 ([#4415](https://github.com/cookiecutter/cookiecutter-django/pull/4415))
|
||||||
|
|
||||||
|
- Update mypy to 1.4.1 ([#4416](https://github.com/cookiecutter/cookiecutter-django/pull/4416))
|
||||||
|
|
||||||
|
## 2023.06.22
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update pygithub to 1.59.0 ([#4410](https://github.com/cookiecutter/cookiecutter-django/pull/4410))
|
||||||
|
|
||||||
|
- Update drf-spectacular to 0.26.3 ([#4411](https://github.com/cookiecutter/cookiecutter-django/pull/4411))
|
||||||
|
|
||||||
|
- Update sentry-sdk to 1.26.0 ([#4409](https://github.com/cookiecutter/cookiecutter-django/pull/4409))
|
||||||
|
|
||||||
|
## 2023.06.21
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Upgrade traefik to 2.10.3 ([#4408](https://github.com/cookiecutter/cookiecutter-django/pull/4408))
|
||||||
|
|
||||||
|
## 2023.06.19
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Auto-update pre-commit hooks ([#4405](https://github.com/cookiecutter/cookiecutter-django/pull/4405))
|
||||||
|
|
||||||
|
- Update celery to 5.3.1 ([#4404](https://github.com/cookiecutter/cookiecutter-django/pull/4404))
|
||||||
|
|
||||||
|
## 2023.06.18
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Fix missing celery env variable when running compilemessages ([#4403](https://github.com/cookiecutter/cookiecutter-django/pull/4403))
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update flower to 2.0.0 ([#4402](https://github.com/cookiecutter/cookiecutter-django/pull/4402))
|
||||||
|
|
||||||
|
## 2023.06.17
|
||||||
|
|
||||||
|
|
||||||
|
## 2023.06.16
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update whitenoise to 6.5.0 ([#4400](https://github.com/cookiecutter/cookiecutter-django/pull/4400))
|
||||||
|
|
||||||
|
- Update django-redis to 5.3.0 ([#4399](https://github.com/cookiecutter/cookiecutter-django/pull/4399))
|
||||||
|
|
||||||
|
- Auto-update pre-commit hooks ([#4395](https://github.com/cookiecutter/cookiecutter-django/pull/4395))
|
||||||
|
|
||||||
|
## 2023.06.14
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update django-cors-headers to 4.1.0 ([#4391](https://github.com/cookiecutter/cookiecutter-django/pull/4391))
|
||||||
|
|
||||||
|
- Update django-upgrade to 1.14.0 ([#4394](https://github.com/cookiecutter/cookiecutter-django/pull/4394))
|
||||||
|
|
||||||
|
- Update django-webpack-loader to 2.0.1 ([#4392](https://github.com/cookiecutter/cookiecutter-django/pull/4392))
|
||||||
|
|
||||||
|
- Update pre-commit to 3.3.3 ([#4390](https://github.com/cookiecutter/cookiecutter-django/pull/4390))
|
||||||
|
|
||||||
|
## 2023.06.11
|
||||||
|
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update pytest to 7.3.2 ([#4384](https://github.com/cookiecutter/cookiecutter-django/pull/4384))
|
||||||
|
|
||||||
|
- Auto-update pre-commit hooks ([#4385](https://github.com/cookiecutter/cookiecutter-django/pull/4385))
|
||||||
|
|
||||||
|
## 2023.06.09
|
||||||
|
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix missing `compilemessages` step before deploying to prod ([#4363](https://github.com/cookiecutter/cookiecutter-django/pull/4363))
|
||||||
|
|
||||||
|
## 2023.06.08
|
||||||
|
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix failure in user view test caused by translations ([#4374](https://github.com/cookiecutter/cookiecutter-django/pull/4374))
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
|
||||||
|
- Update to Python 3.11.4 in production Docker compose ([#4378](https://github.com/cookiecutter/cookiecutter-django/pull/4378))
|
||||||
|
|
||||||
|
- Update to Python 3.11.4 in docs Docker compose ([#4379](https://github.com/cookiecutter/cookiecutter-django/pull/4379))
|
||||||
|
|
||||||
|
- Update to Python 3.11.4 in local Docker compose ([#4380](https://github.com/cookiecutter/cookiecutter-django/pull/4380))
|
||||||
|
|
||||||
|
- Update celery to 5.3.0 ([#4369](https://github.com/cookiecutter/cookiecutter-django/pull/4369))
|
||||||
|
|
||||||
|
- Update werkzeug to 2.3.5 ([#4377](https://github.com/cookiecutter/cookiecutter-django/pull/4377))
|
||||||
|
|
||||||
## 2023.06.07
|
## 2023.06.07
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,13 @@ accept and merge pull requests.
|
||||||
</td>
|
</td>
|
||||||
<td>sfdye</td>
|
<td>sfdye</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Jelmer Draaijer</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/foarsitter">foarsitter</a>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
_Audrey is also the creator of Cookiecutter. Audrey and Daniel are on
|
_Audrey is also the creator of Cookiecutter. Audrey and Daniel are on
|
||||||
|
@ -789,6 +796,13 @@ Listed in alphabetical order.
|
||||||
</td>
|
</td>
|
||||||
<td>fabaff</td>
|
<td>fabaff</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Fateme Fouladkar</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/FatemeFouladkar">FatemeFouladkar</a>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Felipe Arruda</td>
|
<td>Felipe Arruda</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -929,6 +943,13 @@ Listed in alphabetical order.
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>hleroy</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/hleroy">hleroy</a>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Hoai-Thu Vuong</td>
|
<td>Hoai-Thu Vuong</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -950,6 +971,13 @@ Listed in alphabetical order.
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Imran Rahman</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/infraredCoding">infraredCoding</a>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>innicoder</td>
|
<td>innicoder</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -1006,13 +1034,6 @@ Listed in alphabetical order.
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td>Jelmer Draaijer</td>
|
|
||||||
<td>
|
|
||||||
<a href="https://github.com/foarsitter">foarsitter</a>
|
|
||||||
</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Jens Nilsson</td>
|
<td>Jens Nilsson</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -1069,6 +1090,13 @@ Listed in alphabetical order.
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Joseph Hanna</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/sanchimenea">sanchimenea</a>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>jugglinmike</td>
|
<td>jugglinmike</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -1307,6 +1335,13 @@ Listed in alphabetical order.
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>masavini</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/masavini">masavini</a>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Mateusz Ostaszewski</td>
|
<td>Mateusz Ostaszewski</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -1671,6 +1706,13 @@ Listed in alphabetical order.
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Sadra Yahyapour</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/lnxpy">lnxpy</a>
|
||||||
|
</td>
|
||||||
|
<td>lnxpylnxpy</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Sam Collins</td>
|
<td>Sam Collins</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -1692,6 +1734,13 @@ Listed in alphabetical order.
|
||||||
</td>
|
</td>
|
||||||
<td>sebastianreyese</td>
|
<td>sebastianreyese</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Shayan Karimi</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/shywn-mrk">shywn-mrk</a>
|
||||||
|
</td>
|
||||||
|
<td>shywn_mrk</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Simon Rey</td>
|
<td>Simon Rey</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -1776,6 +1825,13 @@ Listed in alphabetical order.
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Tharushan</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/Tharushan">Tharushan</a>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Thibault J.</td>
|
<td>Thibault J.</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -1825,6 +1881,13 @@ Listed in alphabetical order.
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>tmajerech</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/tmajerech">tmajerech</a>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Tom Atkins</td>
|
<td>Tom Atkins</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -1888,6 +1951,13 @@ Listed in alphabetical order.
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>villancikos</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/villancikos">villancikos</a>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Vitaly Babiy</td>
|
<td>Vitaly Babiy</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -1972,6 +2042,13 @@ Listed in alphabetical order.
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>zhaoruibing</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://github.com/zhaoruibing">zhaoruibing</a>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
### Special Thanks
|
### Special Thanks
|
||||||
|
|
27
README.md
27
README.md
|
@ -19,11 +19,11 @@ production-ready Django projects quickly.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- For Django 4.1
|
- For Django 4.2
|
||||||
- Works with Python 3.11
|
- Works with Python 3.11
|
||||||
- Renders Django projects with 100% starting test coverage
|
- Renders Django projects with 100% starting test coverage
|
||||||
- Twitter [Bootstrap](https://github.com/twbs/bootstrap) v5
|
- Twitter [Bootstrap](https://github.com/twbs/bootstrap) v5
|
||||||
- [12-Factor](http://12factor.net/) based settings via [django-environ](https://github.com/joke2k/django-environ)
|
- [12-Factor](https://12factor.net) based settings via [django-environ](https://github.com/joke2k/django-environ)
|
||||||
- Secure by default. We believe in SSL.
|
- Secure by default. We believe in SSL.
|
||||||
- Optimized development and production settings
|
- Optimized development and production settings
|
||||||
- Registration via [django-allauth](https://github.com/pennersr/django-allauth)
|
- Registration via [django-allauth](https://github.com/pennersr/django-allauth)
|
||||||
|
@ -51,15 +51,16 @@ _These features can be enabled during initial project setup._
|
||||||
## Constraints
|
## Constraints
|
||||||
|
|
||||||
- Only maintained 3rd party libraries are used.
|
- Only maintained 3rd party libraries are used.
|
||||||
- Uses PostgreSQL everywhere: 10.19 - 14.1 ([MySQL fork](https://github.com/mabdullahadeel/cookiecutter-django-mysql) also available).
|
- Uses PostgreSQL everywhere: 10 - 15 ([MySQL fork](https://github.com/mabdullahadeel/cookiecutter-django-mysql) also available).
|
||||||
- Environment variables for configuration (This won't work with Apache/mod_wsgi).
|
- Environment variables for configuration (This won't work with Apache/mod_wsgi).
|
||||||
|
|
||||||
## Support this Project!
|
## Support this Project!
|
||||||
|
|
||||||
This project is run by volunteers. Please support them in their efforts to maintain and improve Cookiecutter Django:
|
This project is an open source project run by volunteers. You can sponsor us via [OpenCollective](https://opencollective.com/cookiecutter-django) or individually via GitHub Sponsors:
|
||||||
|
|
||||||
- Daniel Roy Greenfeld, Project Lead ([GitHub](https://github.com/pydanny), [Patreon](https://www.patreon.com/danielroygreenfeld)): expertise in Django and AWS ELB.
|
- Daniel Roy Greenfeld, Project Lead ([GitHub](https://github.com/pydanny), [Patreon](https://www.patreon.com/danielroygreenfeld)): expertise in Django and AWS ELB.
|
||||||
- Fabio C. Barrionuevo, Core Developer ([GitHub](https://github.com/luzfcb)): expertise in Python/Django, hands-on DevOps and frontend experience.
|
- Fabio C. Barrionuevo, Core Developer ([GitHub](https://github.com/luzfcb)): expertise in Python/Django, hands-on DevOps and frontend experience.
|
||||||
|
- Bruno Alla, Core Developer ([GitHub](https://github.com/browniebroke)): expertise in Python/Django and DevOps.
|
||||||
- Nikita Shupeyko, Core Developer ([GitHub](https://github.com/webyneter)): expertise in Python/Django, hands-on DevOps and frontend experience.
|
- Nikita Shupeyko, Core Developer ([GitHub](https://github.com/webyneter)): expertise in Python/Django, hands-on DevOps and frontend experience.
|
||||||
|
|
||||||
Projects that provide financial support to the maintainers:
|
Projects that provide financial support to the maintainers:
|
||||||
|
@ -125,14 +126,19 @@ Answer the prompts with your own desired [options](http://cookiecutter-django.re
|
||||||
Choose from 1, 2 [1]: 1
|
Choose from 1, 2 [1]: 1
|
||||||
timezone [UTC]: America/Los_Angeles
|
timezone [UTC]: America/Los_Angeles
|
||||||
windows [n]: n
|
windows [n]: n
|
||||||
use_pycharm [n]: y
|
Select an editor to use. The choices are:
|
||||||
|
1 - None
|
||||||
|
2 - PyCharm
|
||||||
|
3 - VS Code
|
||||||
|
Choose from 1, 2, 3 [1]: 1
|
||||||
use_docker [n]: n
|
use_docker [n]: n
|
||||||
Select postgresql_version:
|
Select postgresql_version:
|
||||||
1 - 14
|
1 - 15
|
||||||
2 - 13
|
2 - 14
|
||||||
3 - 12
|
3 - 13
|
||||||
4 - 11
|
4 - 12
|
||||||
5 - 10
|
5 - 11
|
||||||
|
6 - 10
|
||||||
Choose from 1, 2, 3, 4, 5 [1]: 1
|
Choose from 1, 2, 3, 4, 5 [1]: 1
|
||||||
Select cloud_provider:
|
Select cloud_provider:
|
||||||
1 - AWS
|
1 - AWS
|
||||||
|
@ -241,6 +247,7 @@ experience better.
|
||||||
|
|
||||||
## Articles
|
## Articles
|
||||||
|
|
||||||
|
- [How to Make Your Own Django Cookiecutter Template!](https://medium.com/@FatemeFouladkar/how-to-make-your-own-django-cookiecutter-template-a753d4cbb8c2) - Aug. 10, 2023
|
||||||
- [Cookiecutter Django With Amazon RDS](https://haseeburrehman.com/posts/cookiecutter-django-with-amazon-rds/) - Apr, 2, 2021
|
- [Cookiecutter Django With Amazon RDS](https://haseeburrehman.com/posts/cookiecutter-django-with-amazon-rds/) - Apr, 2, 2021
|
||||||
- [Complete Walkthrough: Blue/Green Deployment to AWS ECS using GitHub actions](https://github.com/Andrew-Chen-Wang/cookiecutter-django-ecs-github) - June 10, 2020
|
- [Complete Walkthrough: Blue/Green Deployment to AWS ECS using GitHub actions](https://github.com/Andrew-Chen-Wang/cookiecutter-django-ecs-github) - June 10, 2020
|
||||||
- [Using cookiecutter-django with Google Cloud Storage](https://ahhda.github.io/cloud/gce/django/2019/03/12/using-django-cookiecutter-cloud-storage.html) - Mar. 12, 2019
|
- [Using cookiecutter-django with Google Cloud Storage](https://ahhda.github.io/cloud/gce/django/2019/03/12/using-django-cookiecutter-cloud-storage.html) - Mar. 12, 2019
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
"username_type": ["username", "email"],
|
"username_type": ["username", "email"],
|
||||||
"timezone": "UTC",
|
"timezone": "UTC",
|
||||||
"windows": "n",
|
"windows": "n",
|
||||||
"use_pycharm": "n",
|
"editor": ["None", "PyCharm", "VS Code"],
|
||||||
"use_docker": "n",
|
"use_docker": "n",
|
||||||
"postgresql_version": ["14", "13", "12", "11", "10"],
|
"postgresql_version": ["15", "14", "13", "12", "11", "10"],
|
||||||
"cloud_provider": ["AWS", "GCP", "Azure", "None"],
|
"cloud_provider": ["AWS", "GCP", "Azure", "None"],
|
||||||
"mail_service": [
|
"mail_service": [
|
||||||
"Mailgun",
|
"Mailgun",
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
"use_sentry": "n",
|
"use_sentry": "n",
|
||||||
"use_whitenoise": "n",
|
"use_whitenoise": "n",
|
||||||
"use_heroku": "n",
|
"use_heroku": "n",
|
||||||
"ci_tool": ["None", "Travis", "Gitlab", "Github"],
|
"ci_tool": ["None", "Travis", "Gitlab", "Github", "Drone"],
|
||||||
"keep_local_envs_in_vcs": "y",
|
"keep_local_envs_in_vcs": "y",
|
||||||
"debug": "n"
|
"debug": "n"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Deployment with Docker
|
Deployment with Docker
|
||||||
======================
|
======================
|
||||||
|
|
||||||
.. index:: deployment, docker, docker-compose, compose
|
.. index:: deployment, docker, docker compose, compose
|
||||||
|
|
||||||
|
|
||||||
Prerequisites
|
Prerequisites
|
||||||
|
@ -89,7 +89,7 @@ You can read more about this feature and how to configure it, at `Automatic HTTP
|
||||||
Webpack without Whitenoise limitation
|
Webpack without Whitenoise limitation
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
If you opt for Webpack without Whitenoise, Webpack needs to know the static URL at build time, when running ``docker-compose build`` (See ``webpack/prod.config.js``). Depending on your setup, this URL may come from the following environment variables:
|
If you opt for Webpack without Whitenoise, Webpack needs to know the static URL at build time, when running ``docker compose build`` (See ``webpack/prod.config.js``). Depending on your setup, this URL may come from the following environment variables:
|
||||||
|
|
||||||
- ``AWS_STORAGE_BUCKET_NAME``
|
- ``AWS_STORAGE_BUCKET_NAME``
|
||||||
- ``DJANGO_AWS_S3_CUSTOM_DOMAIN``
|
- ``DJANGO_AWS_S3_CUSTOM_DOMAIN``
|
||||||
|
@ -107,7 +107,7 @@ To solve this, you can either:
|
||||||
2. create a ``.env`` file in the root of the project with just variables you need. You'll need to also define them in ``.envs/.production/.django`` (hence duplicating them).
|
2. create a ``.env`` file in the root of the project with just variables you need. You'll need to also define them in ``.envs/.production/.django`` (hence duplicating them).
|
||||||
3. set these variables when running the build command::
|
3. set these variables when running the build command::
|
||||||
|
|
||||||
DJANGO_AWS_S3_CUSTOM_DOMAIN=example.com docker-compose -f production.yml build``.
|
DJANGO_AWS_S3_CUSTOM_DOMAIN=example.com docker compose -f production.yml build``.
|
||||||
|
|
||||||
None of these options are ideal, we're open to suggestions on how to improve this. If you think you have one, please open an issue or a pull request.
|
None of these options are ideal, we're open to suggestions on how to improve this. If you think you have one, please open an issue or a pull request.
|
||||||
|
|
||||||
|
@ -122,42 +122,42 @@ Building & Running Production Stack
|
||||||
|
|
||||||
You will need to build the stack first. To do that, run::
|
You will need to build the stack first. To do that, run::
|
||||||
|
|
||||||
docker-compose -f production.yml build
|
docker compose -f production.yml build
|
||||||
|
|
||||||
Once this is ready, you can run it with::
|
Once this is ready, you can run it with::
|
||||||
|
|
||||||
docker-compose -f production.yml up
|
docker compose -f production.yml up
|
||||||
|
|
||||||
To run the stack and detach the containers, run::
|
To run the stack and detach the containers, run::
|
||||||
|
|
||||||
docker-compose -f production.yml up -d
|
docker compose -f production.yml up -d
|
||||||
|
|
||||||
To run a migration, open up a second terminal and run::
|
To run a migration, open up a second terminal and run::
|
||||||
|
|
||||||
docker-compose -f production.yml run --rm django python manage.py migrate
|
docker compose -f production.yml run --rm django python manage.py migrate
|
||||||
|
|
||||||
To create a superuser, run::
|
To create a superuser, run::
|
||||||
|
|
||||||
docker-compose -f production.yml run --rm django python manage.py createsuperuser
|
docker compose -f production.yml run --rm django python manage.py createsuperuser
|
||||||
|
|
||||||
If you need a shell, run::
|
If you need a shell, run::
|
||||||
|
|
||||||
docker-compose -f production.yml run --rm django python manage.py shell
|
docker compose -f production.yml run --rm django python manage.py shell
|
||||||
|
|
||||||
To check the logs out, run::
|
To check the logs out, run::
|
||||||
|
|
||||||
docker-compose -f production.yml logs
|
docker compose -f production.yml logs
|
||||||
|
|
||||||
If you want to scale your application, run::
|
If you want to scale your application, run::
|
||||||
|
|
||||||
docker-compose -f production.yml up --scale django=4
|
docker compose -f production.yml up --scale django=4
|
||||||
docker-compose -f production.yml up --scale celeryworker=2
|
docker compose -f production.yml up --scale celeryworker=2
|
||||||
|
|
||||||
.. warning:: don't try to scale ``postgres``, ``celerybeat``, or ``traefik``.
|
.. warning:: don't try to scale ``postgres``, ``celerybeat``, or ``traefik``.
|
||||||
|
|
||||||
To see how your containers are doing run::
|
To see how your containers are doing run::
|
||||||
|
|
||||||
docker-compose -f production.yml ps
|
docker compose -f production.yml ps
|
||||||
|
|
||||||
|
|
||||||
Example: Supervisor
|
Example: Supervisor
|
||||||
|
@ -165,12 +165,12 @@ Example: Supervisor
|
||||||
|
|
||||||
Once you are ready with your initial setup, you want to make sure that your application is run by a process manager to
|
Once you are ready with your initial setup, you want to make sure that your application is run by a process manager to
|
||||||
survive reboots and auto restarts in case of an error. You can use the process manager you are most familiar with. All
|
survive reboots and auto restarts in case of an error. You can use the process manager you are most familiar with. All
|
||||||
it needs to do is to run ``docker-compose -f production.yml up`` in your projects root directory.
|
it needs to do is to run ``docker compose -f production.yml up`` in your projects root directory.
|
||||||
|
|
||||||
If you are using ``supervisor``, you can use this file as a starting point::
|
If you are using ``supervisor``, you can use this file as a starting point::
|
||||||
|
|
||||||
[program:{{cookiecutter.project_slug}}]
|
[program:{{cookiecutter.project_slug}}]
|
||||||
command=docker-compose -f production.yml up
|
command=docker compose -f production.yml up
|
||||||
directory=/path/to/{{cookiecutter.project_slug}}
|
directory=/path/to/{{cookiecutter.project_slug}}
|
||||||
redirect_stderr=true
|
redirect_stderr=true
|
||||||
autostart=true
|
autostart=true
|
||||||
|
|
|
@ -32,7 +32,7 @@ Build the Stack
|
||||||
|
|
||||||
This can take a while, especially the first time you run this particular command on your development system::
|
This can take a while, especially the first time you run this particular command on your development system::
|
||||||
|
|
||||||
$ docker-compose -f local.yml build
|
$ docker compose -f local.yml build
|
||||||
|
|
||||||
Generally, if you want to emulate production environment use ``production.yml`` instead. And this is true for any other actions you might need to perform: whenever a switch is required, just do it!
|
Generally, if you want to emulate production environment use ``production.yml`` instead. And this is true for any other actions you might need to perform: whenever a switch is required, just do it!
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ This brings up both Django and PostgreSQL. The first time it is run it might tak
|
||||||
|
|
||||||
Open a terminal at the project root and run the following for local development::
|
Open a terminal at the project root and run the following for local development::
|
||||||
|
|
||||||
$ docker-compose -f local.yml up
|
$ docker compose -f local.yml up
|
||||||
|
|
||||||
You can also set the environment variable ``COMPOSE_FILE`` pointing to ``local.yml`` like this::
|
You can also set the environment variable ``COMPOSE_FILE`` pointing to ``local.yml`` like this::
|
||||||
|
|
||||||
|
@ -59,23 +59,25 @@ You can also set the environment variable ``COMPOSE_FILE`` pointing to ``local.y
|
||||||
|
|
||||||
And then run::
|
And then run::
|
||||||
|
|
||||||
$ docker-compose up
|
$ docker compose up
|
||||||
|
|
||||||
To run in a detached (background) mode, just::
|
To run in a detached (background) mode, just::
|
||||||
|
|
||||||
$ docker-compose up -d
|
$ docker compose up -d
|
||||||
|
|
||||||
|
|
||||||
|
The site should start and be accessible at http://localhost:3000 if you selected Webpack or Gulp as frontend pipeline and http://localhost:8000 otherwise.
|
||||||
|
|
||||||
Execute Management Commands
|
Execute Management Commands
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
As with any shell command that we wish to run in our container, this is done using the ``docker-compose -f local.yml run --rm`` command: ::
|
As with any shell command that we wish to run in our container, this is done using the ``docker compose -f local.yml run --rm`` command: ::
|
||||||
|
|
||||||
$ docker-compose -f local.yml run --rm django python manage.py migrate
|
$ docker compose -f local.yml run --rm django python manage.py migrate
|
||||||
$ docker-compose -f local.yml run --rm django python manage.py createsuperuser
|
$ docker compose -f local.yml run --rm django python manage.py createsuperuser
|
||||||
|
|
||||||
Here, ``django`` is the target service we are executing the commands against.
|
Here, ``django`` is the target service we are executing the commands against.
|
||||||
|
Also, please note that the ``docker exec`` does not work for running management commands.
|
||||||
|
|
||||||
(Optionally) Designate your Docker Development Server IP
|
(Optionally) Designate your Docker Development Server IP
|
||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
|
@ -154,8 +156,8 @@ You have to modify the relevant requirement file: base, local or production by a
|
||||||
|
|
||||||
To get this change picked up, you'll need to rebuild the image(s) and restart the running container: ::
|
To get this change picked up, you'll need to rebuild the image(s) and restart the running container: ::
|
||||||
|
|
||||||
docker-compose -f local.yml build
|
docker compose -f local.yml build
|
||||||
docker-compose -f local.yml up
|
docker compose -f local.yml up
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
@ -169,7 +171,7 @@ If you are using the following within your code to debug: ::
|
||||||
|
|
||||||
Then you may need to run the following for it to work as desired: ::
|
Then you may need to run the following for it to work as desired: ::
|
||||||
|
|
||||||
$ docker-compose -f local.yml run --rm --service-ports django
|
$ docker compose -f local.yml run --rm --service-ports django
|
||||||
|
|
||||||
|
|
||||||
django-debug-toolbar
|
django-debug-toolbar
|
||||||
|
@ -229,7 +231,12 @@ By default, it's enabled both in local and production environments (``local.yml`
|
||||||
Using Webpack or Gulp
|
Using Webpack or Gulp
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
When using Webpack or Gulp as the ``frontend_pipeline`` option, you should access your application at the address of the ``node`` service in order to see your correct styles. This is http://localhost:3000 by default. When using any of the other ``frontend_pipeline`` options, you should use the address of the ``django`` service, http://localhost:8000.
|
If you've opted for Gulp or Webpack as front-end pipeline, the project comes configured with `Sass`_ compilation and `live reloading`_. As you change your Sass/JS source files, the task runner will automatically rebuild the corresponding CSS and JS assets and reload them in your browser without refreshing the page.
|
||||||
|
|
||||||
|
The stack comes with a dedicated node service to build the static assets, watch for changes and proxy requests to the Django app with live reloading scripts injected in the response. For everything to work smoothly, you need to access the application at the port served by the node service, which is http://localhost:3000 by default.
|
||||||
|
|
||||||
|
.. _Sass: https://sass-lang.com/
|
||||||
|
.. _live reloading: https://browsersync.io
|
||||||
|
|
||||||
Developing locally with HTTPS
|
Developing locally with HTTPS
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
@ -309,7 +316,7 @@ You should allow the new hostname. ::
|
||||||
|
|
||||||
Rebuild your ``docker`` application. ::
|
Rebuild your ``docker`` application. ::
|
||||||
|
|
||||||
$ docker-compose -f local.yml up -d --build
|
$ docker compose -f local.yml up -d --build
|
||||||
|
|
||||||
Go to your browser and type in your URL bar ``https://my-dev-env.local``
|
Go to your browser and type in your URL bar ``https://my-dev-env.local``
|
||||||
|
|
||||||
|
@ -323,3 +330,26 @@ See `https with nginx`_ for more information on this configuration.
|
||||||
Add ``certs/*`` to the ``.gitignore`` file. This allows the folder to be included in the repo but its contents to be ignored.
|
Add ``certs/*`` to the ``.gitignore`` file. This allows the folder to be included in the repo but its contents to be ignored.
|
||||||
|
|
||||||
*This configuration is for local development environments only. Do not use this for production since you might expose your local* ``rootCA-key.pem``.
|
*This configuration is for local development environments only. Do not use this for production since you might expose your local* ``rootCA-key.pem``.
|
||||||
|
|
||||||
|
Webpack
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
If you are using Webpack:
|
||||||
|
|
||||||
|
1. On the ``nginx-proxy`` service in ``local.yml``, change ``depends_on`` to ``node`` instead of ``django``.
|
||||||
|
|
||||||
|
2. On the ``node`` service in ``local.yml``, add the following environment configuration:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- VIRTUAL_HOST=my-dev-env.local
|
||||||
|
- VIRTUAL_PORT=3000
|
||||||
|
|
||||||
|
3. Add the following configuration to the ``devServer`` section of ``webpack/dev.config.js``:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
client: {
|
||||||
|
webSocketURL: 'auto://0.0.0.0:0/ws', // note the `:0` after `0.0.0.0`
|
||||||
|
},
|
||||||
|
|
|
@ -80,10 +80,12 @@ First things first.
|
||||||
|
|
||||||
$ python manage.py runserver 0.0.0.0:8000
|
$ python manage.py runserver 0.0.0.0:8000
|
||||||
|
|
||||||
or if you're running asynchronously: ::
|
or if you're running asynchronously: ::
|
||||||
|
|
||||||
$ uvicorn config.asgi:application --host 0.0.0.0 --reload --reload-include '*.html'
|
$ uvicorn config.asgi:application --host 0.0.0.0 --reload --reload-include '*.html'
|
||||||
|
|
||||||
|
If you've opted for Webpack or Gulp as frontend pipeline, please see the :ref:`dedicated section <bare-metal-webpack-gulp>` below.
|
||||||
|
|
||||||
.. _PostgreSQL: https://www.postgresql.org/download/
|
.. _PostgreSQL: https://www.postgresql.org/download/
|
||||||
.. _Redis: https://redis.io/download
|
.. _Redis: https://redis.io/download
|
||||||
.. _CookieCutter: https://github.com/cookiecutter/cookiecutter
|
.. _CookieCutter: https://github.com/cookiecutter/cookiecutter
|
||||||
|
@ -169,10 +171,12 @@ You can also use Django admin to queue up tasks, thanks to the `django-celerybea
|
||||||
.. _django-celerybeat: https://django-celery-beat.readthedocs.io/en/latest/
|
.. _django-celerybeat: https://django-celery-beat.readthedocs.io/en/latest/
|
||||||
|
|
||||||
|
|
||||||
Sass Compilation & Live Reloading
|
.. _bare-metal-webpack-gulp:
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
If you've opted for Gulp or Webpack as front-end pipeline, the project comes configured with `Sass`_ compilation and `live reloading`_. As you change you Sass/JS source files, the task runner will automatically rebuild the corresponding CSS and JS assets and reload them in your browser without refreshing the page.
|
Using Webpack or Gulp
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
If you've opted for Gulp or Webpack as front-end pipeline, the project comes configured with `Sass`_ compilation and `live reloading`_. As you change your Sass/JS source files, the task runner will automatically rebuild the corresponding CSS and JS assets and reload them in your browser without refreshing the page.
|
||||||
|
|
||||||
#. Make sure that `Node.js`_ v18 is installed on your machine.
|
#. Make sure that `Node.js`_ v18 is installed on your machine.
|
||||||
#. In the project root, install the JS dependencies with::
|
#. In the project root, install the JS dependencies with::
|
||||||
|
@ -183,9 +187,12 @@ If you've opted for Gulp or Webpack as front-end pipeline, the project comes con
|
||||||
|
|
||||||
$ npm run dev
|
$ npm run dev
|
||||||
|
|
||||||
The app will now run with live reloading enabled, applying front-end changes dynamically.
|
This will start 2 processes in parallel: the static assets build loop on one side, and the Django server on the other.
|
||||||
|
|
||||||
|
#. Access your application at the address of the ``node`` service in order to see your correct styles. This is http://localhost:3000 by default.
|
||||||
|
|
||||||
|
.. note:: Do NOT access the application using the Django port (8000 by default), as it will result in broken styles and 404s when accessing static assets.
|
||||||
|
|
||||||
.. note:: The task will start 2 processes in parallel: the static assets build loop on one side, and the Django server on the other. You do NOT need to run Django as your would normally with ``manage.py runserver``.
|
|
||||||
|
|
||||||
.. _Node.js: http://nodejs.org/download/
|
.. _Node.js: http://nodejs.org/download/
|
||||||
.. _Sass: https://sass-lang.com/
|
.. _Sass: https://sass-lang.com/
|
||||||
|
|
|
@ -8,7 +8,7 @@ Prerequisites
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
#. the project was generated with ``use_docker`` set to ``y``;
|
#. the project was generated with ``use_docker`` set to ``y``;
|
||||||
#. the stack is up and running: ``docker-compose -f local.yml up -d postgres``.
|
#. the stack is up and running: ``docker compose -f local.yml up -d postgres``.
|
||||||
|
|
||||||
|
|
||||||
Creating a Backup
|
Creating a Backup
|
||||||
|
@ -16,7 +16,7 @@ Creating a Backup
|
||||||
|
|
||||||
To create a backup, run::
|
To create a backup, run::
|
||||||
|
|
||||||
$ docker-compose -f local.yml exec postgres backup
|
$ docker compose -f local.yml exec postgres backup
|
||||||
|
|
||||||
Assuming your project's database is named ``my_project`` here is what you will see: ::
|
Assuming your project's database is named ``my_project`` here is what you will see: ::
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ Viewing the Existing Backups
|
||||||
|
|
||||||
To list existing backups, ::
|
To list existing backups, ::
|
||||||
|
|
||||||
$ docker-compose -f local.yml exec postgres backups
|
$ docker compose -f local.yml exec postgres backups
|
||||||
|
|
||||||
These are the sample contents of ``/backups``: ::
|
These are the sample contents of ``/backups``: ::
|
||||||
|
|
||||||
|
@ -55,9 +55,9 @@ With a single backup file copied to ``.`` that would be ::
|
||||||
|
|
||||||
$ docker cp 9c5c3f055843:/backups/backup_2018_03_13T09_05_07.sql.gz .
|
$ docker cp 9c5c3f055843:/backups/backup_2018_03_13T09_05_07.sql.gz .
|
||||||
|
|
||||||
You can also get the container ID using ``docker-compose -f local.yml ps -q postgres`` so if you want to automate your backups, you don't have to check the container ID manually every time. Here is the full command ::
|
You can also get the container ID using ``docker compose -f local.yml ps -q postgres`` so if you want to automate your backups, you don't have to check the container ID manually every time. Here is the full command ::
|
||||||
|
|
||||||
$ docker cp $(docker-compose -f local.yml ps -q postgres):/backups ./backups
|
$ docker cp $(docker compose -f local.yml ps -q postgres):/backups ./backups
|
||||||
|
|
||||||
.. _`command`: https://docs.docker.com/engine/reference/commandline/cp/
|
.. _`command`: https://docs.docker.com/engine/reference/commandline/cp/
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ Restoring from the Existing Backup
|
||||||
|
|
||||||
To restore from one of the backups you have already got (take the ``backup_2018_03_13T09_05_07.sql.gz`` for example), ::
|
To restore from one of the backups you have already got (take the ``backup_2018_03_13T09_05_07.sql.gz`` for example), ::
|
||||||
|
|
||||||
$ docker-compose -f local.yml exec postgres restore backup_2018_03_13T09_05_07.sql.gz
|
$ docker compose -f local.yml exec postgres restore backup_2018_03_13T09_05_07.sql.gz
|
||||||
|
|
||||||
You will see something like ::
|
You will see something like ::
|
||||||
|
|
||||||
|
@ -94,5 +94,5 @@ Backup to Amazon S3
|
||||||
----------------------------------
|
----------------------------------
|
||||||
For uploading your backups to Amazon S3 you can use the aws cli container. There is an upload command for uploading the postgres /backups directory recursively and there is a download command for downloading a specific backup. The default S3 environment variables are used. ::
|
For uploading your backups to Amazon S3 you can use the aws cli container. There is an upload command for uploading the postgres /backups directory recursively and there is a download command for downloading a specific backup. The default S3 environment variables are used. ::
|
||||||
|
|
||||||
$ docker-compose -f production.yml run --rm awscli upload
|
$ docker compose -f production.yml run --rm awscli upload
|
||||||
$ docker-compose -f production.yml run --rm awscli download backup_2018_03_13T09_05_07.sql.gz
|
$ docker compose -f production.yml run --rm awscli download backup_2018_03_13T09_05_07.sql.gz
|
||||||
|
|
|
@ -11,7 +11,7 @@ After you have set up to `develop locally`_, run the following command from the
|
||||||
|
|
||||||
If you set up your project to `develop locally with docker`_, run the following command: ::
|
If you set up your project to `develop locally with docker`_, run the following command: ::
|
||||||
|
|
||||||
$ docker-compose -f local.yml up docs
|
$ docker compose -f local.yml up docs
|
||||||
|
|
||||||
Navigate to port 9000 on your host to see the documentation. This will be opened automatically at `localhost`_ for local, non-docker development.
|
Navigate to port 9000 on your host to see the documentation. This will be opened automatically at `localhost`_ for local, non-docker development.
|
||||||
|
|
||||||
|
|
|
@ -53,20 +53,25 @@ timezone:
|
||||||
windows:
|
windows:
|
||||||
Indicates whether the project should be configured for development on Windows.
|
Indicates whether the project should be configured for development on Windows.
|
||||||
|
|
||||||
use_pycharm:
|
editor:
|
||||||
Indicates whether the project should be configured for development with PyCharm_.
|
Select an editor to use. The choices are:
|
||||||
|
|
||||||
|
1. None
|
||||||
|
2. PyCharm_
|
||||||
|
3. `VS Code`_
|
||||||
|
|
||||||
use_docker:
|
use_docker:
|
||||||
Indicates whether the project should be configured to use Docker_ and `Docker Compose`_.
|
Indicates whether the project should be configured to use Docker_, `Docker Compose`_ and `devcontainer`_.
|
||||||
|
|
||||||
postgresql_version:
|
postgresql_version:
|
||||||
Select a PostgreSQL_ version to use. The choices are:
|
Select a PostgreSQL_ version to use. The choices are:
|
||||||
|
|
||||||
1. 14
|
1. 15
|
||||||
2. 13
|
2. 14
|
||||||
3. 12
|
3. 13
|
||||||
4. 11
|
4. 12
|
||||||
5. 10
|
5. 11
|
||||||
|
6. 10
|
||||||
|
|
||||||
cloud_provider:
|
cloud_provider:
|
||||||
Select a cloud provider for static & media files. The choices are:
|
Select a cloud provider for static & media files. The choices are:
|
||||||
|
@ -130,6 +135,7 @@ ci_tool:
|
||||||
2. `Travis CI`_
|
2. `Travis CI`_
|
||||||
3. `Gitlab CI`_
|
3. `Gitlab CI`_
|
||||||
4. `Github Actions`_
|
4. `Github Actions`_
|
||||||
|
5. `Drone CI`_
|
||||||
|
|
||||||
keep_local_envs_in_vcs:
|
keep_local_envs_in_vcs:
|
||||||
Indicates whether the project's ``.envs/.local/`` should be kept in VCS
|
Indicates whether the project's ``.envs/.local/`` should be kept in VCS
|
||||||
|
@ -148,9 +154,11 @@ debug:
|
||||||
.. _Apache Software License 2.0: http://www.apache.org/licenses/LICENSE-2.0
|
.. _Apache Software License 2.0: http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
.. _PyCharm: https://www.jetbrains.com/pycharm/
|
.. _PyCharm: https://www.jetbrains.com/pycharm/
|
||||||
|
.. _VS Code: https://github.com/microsoft/vscode
|
||||||
|
|
||||||
.. _Docker: https://github.com/docker/docker
|
.. _Docker: https://github.com/docker/docker
|
||||||
.. _Docker Compose: https://docs.docker.com/compose/
|
.. _Docker Compose: https://docs.docker.com/compose/
|
||||||
|
.. _devcontainer: https://containers.dev/
|
||||||
|
|
||||||
.. _PostgreSQL: https://www.postgresql.org/docs/
|
.. _PostgreSQL: https://www.postgresql.org/docs/
|
||||||
|
|
||||||
|
@ -189,4 +197,6 @@ debug:
|
||||||
|
|
||||||
.. _GitLab CI: https://docs.gitlab.com/ee/ci/
|
.. _GitLab CI: https://docs.gitlab.com/ee/ci/
|
||||||
|
|
||||||
|
.. _Drone CI: https://docs.drone.io/pipeline/overview/
|
||||||
|
|
||||||
.. _Github Actions: https://docs.github.com/en/actions
|
.. _Github Actions: https://docs.github.com/en/actions
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
sphinx==6.2.1
|
sphinx==6.2.1
|
||||||
sphinx-rtd-theme==1.2.2
|
sphinx-rtd-theme==1.2.2
|
||||||
myst-parser==1.0.0
|
myst-parser==2.0.0
|
||||||
|
|
|
@ -81,3 +81,6 @@ Other Environment Settings
|
||||||
|
|
||||||
DJANGO_ACCOUNT_ALLOW_REGISTRATION (=True)
|
DJANGO_ACCOUNT_ALLOW_REGISTRATION (=True)
|
||||||
Allow enable or disable user registration through `django-allauth` without disabling other characteristics like authentication and account management. (Django Setting: ACCOUNT_ALLOW_REGISTRATION)
|
Allow enable or disable user registration through `django-allauth` without disabling other characteristics like authentication and account management. (Django Setting: ACCOUNT_ALLOW_REGISTRATION)
|
||||||
|
|
||||||
|
DJANGO_ADMIN_FORCE_ALLAUTH (=False)
|
||||||
|
Force the `admin` sign in process to go through the `django-allauth` workflow.
|
||||||
|
|
|
@ -19,7 +19,7 @@ You will get a readout of the `users` app that has already been set up with test
|
||||||
|
|
||||||
If you set up your project to `develop locally with docker`_, run the following command: ::
|
If you set up your project to `develop locally with docker`_, run the following command: ::
|
||||||
|
|
||||||
$ docker-compose -f local.yml run --rm django pytest
|
$ docker compose -f local.yml run --rm django pytest
|
||||||
|
|
||||||
Targeting particular apps for testing in ``docker`` follows a similar pattern as previously shown above.
|
Targeting particular apps for testing in ``docker`` follows a similar pattern as previously shown above.
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ Once the tests are complete, in order to see the code coverage, run the followin
|
||||||
|
|
||||||
If you're running the project locally with Docker, use these commands instead: ::
|
If you're running the project locally with Docker, use these commands instead: ::
|
||||||
|
|
||||||
$ docker-compose -f local.yml run --rm django coverage run -m pytest
|
$ docker compose -f local.yml run --rm django coverage run -m pytest
|
||||||
$ docker-compose -f local.yml run --rm django coverage report
|
$ docker compose -f local.yml run --rm django coverage report
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|
|
@ -24,13 +24,13 @@ Examples of logs::
|
||||||
If you recreate the project multiple times with the same name, Docker would preserve the volumes for the postgres container between projects. Here is what happens:
|
If you recreate the project multiple times with the same name, Docker would preserve the volumes for the postgres container between projects. Here is what happens:
|
||||||
|
|
||||||
#. You generate the project the first time. The .env postgres file is populated with the random password
|
#. You generate the project the first time. The .env postgres file is populated with the random password
|
||||||
#. You run the docker-compose and the containers are created. The postgres container creates the database based on the .env file credentials
|
#. You run the docker compose and the containers are created. The postgres container creates the database based on the .env file credentials
|
||||||
#. You "regenerate" the project with the same name, so the postgres .env file is populated with a new random password
|
#. You "regenerate" the project with the same name, so the postgres .env file is populated with a new random password
|
||||||
#. You run docker-compose. Since the names of the containers are the same, docker will try to start them (not create them from scratch i.e. it won't execute the Dockerfile to recreate the database). When this happens, it tries to start the database based on the new credentials which do not match the ones that the database was created with, and you get the error message above.
|
#. You run docker compose. Since the names of the containers are the same, docker will try to start them (not create them from scratch i.e. it won't execute the Dockerfile to recreate the database). When this happens, it tries to start the database based on the new credentials which do not match the ones that the database was created with, and you get the error message above.
|
||||||
|
|
||||||
To fix this, you can either:
|
To fix this, you can either:
|
||||||
|
|
||||||
- Clear your project-related Docker cache with ``docker-compose -f local.yml down --volumes --rmi all``.
|
- Clear your project-related Docker cache with ``docker compose -f local.yml down --volumes --rmi all``.
|
||||||
- Use the Docker volume sub-commands to find volumes (`ls`_) and remove them (`rm`_).
|
- Use the Docker volume sub-commands to find volumes (`ls`_) and remove them (`rm`_).
|
||||||
- Use the `prune`_ command to clear system-wide (use with care!).
|
- Use the `prune`_ command to clear system-wide (use with care!).
|
||||||
|
|
||||||
|
|
|
@ -74,12 +74,13 @@ def remove_pycharm_files():
|
||||||
|
|
||||||
|
|
||||||
def remove_docker_files():
|
def remove_docker_files():
|
||||||
|
shutil.rmtree(".devcontainer")
|
||||||
shutil.rmtree("compose")
|
shutil.rmtree("compose")
|
||||||
|
|
||||||
file_names = ["local.yml", "production.yml", ".dockerignore"]
|
file_names = ["local.yml", "production.yml", ".dockerignore"]
|
||||||
for file_name in file_names:
|
for file_name in file_names:
|
||||||
os.remove(file_name)
|
os.remove(file_name)
|
||||||
if "{{ cookiecutter.use_pycharm }}".lower() == "y":
|
if "{{ cookiecutter.editor }}" == "PyCharm":
|
||||||
file_names = ["docker_compose_up_django.xml", "docker_compose_up_docs.xml"]
|
file_names = ["docker_compose_up_django.xml", "docker_compose_up_docs.xml"]
|
||||||
for file_name in file_names:
|
for file_name in file_names:
|
||||||
os.remove(os.path.join(".idea", "runConfigurations", file_name))
|
os.remove(os.path.join(".idea", "runConfigurations", file_name))
|
||||||
|
@ -96,10 +97,6 @@ def remove_heroku_files():
|
||||||
# don't remove the file if we are using travisci but not using heroku
|
# don't remove the file if we are using travisci but not using heroku
|
||||||
continue
|
continue
|
||||||
os.remove(file_name)
|
os.remove(file_name)
|
||||||
remove_heroku_build_hooks()
|
|
||||||
|
|
||||||
|
|
||||||
def remove_heroku_build_hooks():
|
|
||||||
shutil.rmtree("bin")
|
shutil.rmtree("bin")
|
||||||
|
|
||||||
|
|
||||||
|
@ -186,6 +183,7 @@ def handle_js_runner(choice, use_docker, use_async):
|
||||||
"browser-sync",
|
"browser-sync",
|
||||||
"cssnano",
|
"cssnano",
|
||||||
"gulp",
|
"gulp",
|
||||||
|
"gulp-concat",
|
||||||
"gulp-imagemin",
|
"gulp-imagemin",
|
||||||
"gulp-plumber",
|
"gulp-plumber",
|
||||||
"gulp-postcss",
|
"gulp-postcss",
|
||||||
|
@ -210,6 +208,24 @@ def handle_js_runner(choice, use_docker, use_async):
|
||||||
remove_gulp_files()
|
remove_gulp_files()
|
||||||
|
|
||||||
|
|
||||||
|
def remove_prettier_pre_commit():
|
||||||
|
with open(".pre-commit-config.yaml", "r") as fd:
|
||||||
|
content = fd.readlines()
|
||||||
|
|
||||||
|
removing = False
|
||||||
|
new_lines = []
|
||||||
|
for line in content:
|
||||||
|
if removing and "- repo:" in line:
|
||||||
|
removing = False
|
||||||
|
if "mirrors-prettier" in line:
|
||||||
|
removing = True
|
||||||
|
if not removing:
|
||||||
|
new_lines.append(line)
|
||||||
|
|
||||||
|
with open(".pre-commit-config.yaml", "w") as fd:
|
||||||
|
fd.writelines(new_lines)
|
||||||
|
|
||||||
|
|
||||||
def remove_celery_files():
|
def remove_celery_files():
|
||||||
file_names = [
|
file_names = [
|
||||||
os.path.join("config", "celery_app.py"),
|
os.path.join("config", "celery_app.py"),
|
||||||
|
@ -241,6 +257,10 @@ def remove_dotgithub_folder():
|
||||||
shutil.rmtree(".github")
|
shutil.rmtree(".github")
|
||||||
|
|
||||||
|
|
||||||
|
def remove_dotdrone_file():
|
||||||
|
os.remove(".drone.yml")
|
||||||
|
|
||||||
|
|
||||||
def generate_random_string(length, using_digits=False, using_ascii_letters=False, using_punctuation=False):
|
def generate_random_string(length, using_digits=False, using_ascii_letters=False, using_punctuation=False):
|
||||||
"""
|
"""
|
||||||
Example:
|
Example:
|
||||||
|
@ -431,7 +451,7 @@ def main():
|
||||||
if "{{ cookiecutter.username_type }}" == "username":
|
if "{{ cookiecutter.username_type }}" == "username":
|
||||||
remove_custom_user_manager_files()
|
remove_custom_user_manager_files()
|
||||||
|
|
||||||
if "{{ cookiecutter.use_pycharm }}".lower() == "n":
|
if "{{ cookiecutter.editor }}" != "PyCharm":
|
||||||
remove_pycharm_files()
|
remove_pycharm_files()
|
||||||
|
|
||||||
if "{{ cookiecutter.use_docker }}".lower() == "y":
|
if "{{ cookiecutter.use_docker }}".lower() == "y":
|
||||||
|
@ -444,15 +464,13 @@ def main():
|
||||||
|
|
||||||
if "{{ cookiecutter.use_heroku }}".lower() == "n":
|
if "{{ cookiecutter.use_heroku }}".lower() == "n":
|
||||||
remove_heroku_files()
|
remove_heroku_files()
|
||||||
elif "{{ cookiecutter.frontend_pipeline }}" != "Django Compressor":
|
|
||||||
remove_heroku_build_hooks()
|
|
||||||
|
|
||||||
if "{{ cookiecutter.use_docker }}".lower() == "n" and "{{ cookiecutter.use_heroku }}".lower() == "n":
|
if "{{ cookiecutter.use_docker }}".lower() == "n" and "{{ cookiecutter.use_heroku }}".lower() == "n":
|
||||||
if "{{ cookiecutter.keep_local_envs_in_vcs }}".lower() == "y":
|
if "{{ cookiecutter.keep_local_envs_in_vcs }}".lower() == "y":
|
||||||
print(
|
print(
|
||||||
INFO + ".env(s) are only utilized when Docker Compose and/or "
|
INFO + ".env(s) are only utilized when Docker Compose and/or "
|
||||||
"Heroku support is enabled so keeping them does not "
|
"Heroku support is enabled so keeping them does not make sense "
|
||||||
"make sense given your current setup." + TERMINATOR
|
"given your current setup." + TERMINATOR
|
||||||
)
|
)
|
||||||
remove_envs_and_associated_files()
|
remove_envs_and_associated_files()
|
||||||
else:
|
else:
|
||||||
|
@ -466,6 +484,7 @@ def main():
|
||||||
remove_webpack_files()
|
remove_webpack_files()
|
||||||
remove_sass_files()
|
remove_sass_files()
|
||||||
remove_packagejson_file()
|
remove_packagejson_file()
|
||||||
|
remove_prettier_pre_commit()
|
||||||
if "{{ cookiecutter.use_docker }}".lower() == "y":
|
if "{{ cookiecutter.use_docker }}".lower() == "y":
|
||||||
remove_node_dockerfile()
|
remove_node_dockerfile()
|
||||||
else:
|
else:
|
||||||
|
@ -496,6 +515,9 @@ def main():
|
||||||
if "{{ cookiecutter.ci_tool }}" != "Github":
|
if "{{ cookiecutter.ci_tool }}" != "Github":
|
||||||
remove_dotgithub_folder()
|
remove_dotgithub_folder()
|
||||||
|
|
||||||
|
if "{{ cookiecutter.ci_tool }}" != "Drone":
|
||||||
|
remove_dotdrone_file()
|
||||||
|
|
||||||
if "{{ cookiecutter.use_drf }}".lower() == "n":
|
if "{{ cookiecutter.use_drf }}".lower() == "n":
|
||||||
remove_drf_starter_files()
|
remove_drf_starter_files()
|
||||||
|
|
||||||
|
|
|
@ -27,3 +27,24 @@ known_first_party = [
|
||||||
"scripts",
|
"scripts",
|
||||||
"hooks",
|
"hooks",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# ==== djLint ====
|
||||||
|
[tool.djlint]
|
||||||
|
blank_line_after_tag = "load,extends"
|
||||||
|
close_void_tags = true
|
||||||
|
format_css = true
|
||||||
|
format_js = true
|
||||||
|
# TODO: remove T002 when fixed https://github.com/Riverside-Healthcare/djLint/issues/687
|
||||||
|
ignore = "H006,H030,H031,T002,T028"
|
||||||
|
ignore_blocks = "raw"
|
||||||
|
include = "H017,H035"
|
||||||
|
indent = 2
|
||||||
|
max_line_length = 119
|
||||||
|
profile = "jinja"
|
||||||
|
|
||||||
|
[tool.djlint.css]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[tool.djlint.js]
|
||||||
|
indent_size = 2
|
||||||
|
|
|
@ -1,27 +1,28 @@
|
||||||
cookiecutter==2.1.1
|
cookiecutter==2.3.0
|
||||||
sh==2.0.4; sys_platform != "win32"
|
sh==2.0.6; sys_platform != "win32"
|
||||||
binaryornot==0.4.4
|
binaryornot==0.4.4
|
||||||
|
|
||||||
# Code quality
|
# Code quality
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
black==23.3.0
|
black==23.7.0
|
||||||
isort==5.12.0
|
isort==5.12.0
|
||||||
flake8==6.0.0
|
flake8==6.1.0
|
||||||
django-upgrade==1.13.0
|
django-upgrade==1.14.0
|
||||||
pre-commit==3.3.2
|
djlint==1.32.1
|
||||||
|
pre-commit==3.3.3
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
tox==4.6.0
|
tox==4.8.0
|
||||||
pytest==7.3.1
|
pytest==7.4.0
|
||||||
pytest-xdist==3.3.1
|
pytest-xdist==3.3.1
|
||||||
pytest-cookies==0.7.0
|
pytest-cookies==0.7.0
|
||||||
pytest-instafail==0.5.0
|
pytest-instafail==0.5.0
|
||||||
pyyaml==6.0
|
pyyaml==6.0.1
|
||||||
|
|
||||||
# Scripting
|
# Scripting
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
PyGithub==1.58.2
|
PyGithub==1.59.1
|
||||||
gitpython==3.1.31
|
gitpython==3.1.32
|
||||||
jinja2==3.1.2
|
jinja2==3.1.2
|
||||||
requests==2.31.0
|
requests==2.31.0
|
||||||
|
|
|
@ -182,9 +182,8 @@ class GitHubManager:
|
||||||
if not matches:
|
if not matches:
|
||||||
continue
|
continue
|
||||||
issue_version = DjVersion.parse(matches.group(1))
|
issue_version = DjVersion.parse(matches.group(1))
|
||||||
if self.base_dj_version > issue_version:
|
if self.base_dj_version >= issue_version:
|
||||||
issue.edit(state="closed")
|
self.close_issue(issue)
|
||||||
print(f"Closed issue {issue.title} (ID: [{issue.id}]({issue.url}))")
|
|
||||||
else:
|
else:
|
||||||
self.existing_issues[issue_version] = issue
|
self.existing_issues[issue_version] = issue
|
||||||
|
|
||||||
|
@ -269,6 +268,11 @@ class GitHubManager:
|
||||||
issue = self.repo.create_issue(f"[Update Django] Django {needed_dj_version}", description)
|
issue = self.repo.create_issue(f"[Update Django] Django {needed_dj_version}", description)
|
||||||
issue.add_to_labels(f"django{needed_dj_version}")
|
issue.add_to_labels(f"django{needed_dj_version}")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def close_issue(issue: Issue):
|
||||||
|
issue.edit(state="closed")
|
||||||
|
print(f"Closed issue {issue.title} (ID: [{issue.id}]({issue.url}))")
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
for version in self.needed_dj_versions:
|
for version in self.needed_dj_versions:
|
||||||
print(f"Handling GitHub issue for Django {version}")
|
print(f"Handling GitHub issue for Django {version}")
|
||||||
|
@ -280,10 +284,15 @@ class GitHubManager:
|
||||||
def main(django_max_version=None) -> None:
|
def main(django_max_version=None) -> None:
|
||||||
# Check if there are any djs
|
# Check if there are any djs
|
||||||
current_dj, latest_djs = get_all_latest_django_versions(django_max_version=django_max_version)
|
current_dj, latest_djs = get_all_latest_django_versions(django_max_version=django_max_version)
|
||||||
if not latest_djs:
|
|
||||||
sys.exit(0)
|
# Run the setup, which might close old issues
|
||||||
manager = GitHubManager(current_dj, latest_djs)
|
manager = GitHubManager(current_dj, latest_djs)
|
||||||
manager.setup()
|
manager.setup()
|
||||||
|
|
||||||
|
if not latest_djs:
|
||||||
|
print("No new Django versions to update. Exiting...")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
manager.generate()
|
manager.generate()
|
||||||
|
|
||||||
|
|
||||||
|
|
6
setup.py
6
setup.py
|
@ -5,9 +5,9 @@ except ImportError:
|
||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
|
|
||||||
# We use calendar versioning
|
# We use calendar versioning
|
||||||
version = "2023.06.07"
|
version = "2023.08.10"
|
||||||
|
|
||||||
with open("README.rst") as readme_file:
|
with open("README.md") as readme_file:
|
||||||
long_description = readme_file.read()
|
long_description = readme_file.read()
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
|
@ -24,7 +24,7 @@ setup(
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"Development Status :: 4 - Beta",
|
"Development Status :: 4 - Beta",
|
||||||
"Environment :: Console",
|
"Environment :: Console",
|
||||||
"Framework :: Django :: 4.1",
|
"Framework :: Django :: 4.2",
|
||||||
"Intended Audience :: Developers",
|
"Intended Audience :: Developers",
|
||||||
"Natural Language :: English",
|
"Natural Language :: English",
|
||||||
"License :: OSI Approved :: BSD License",
|
"License :: OSI Approved :: BSD License",
|
||||||
|
|
|
@ -52,10 +52,12 @@ SUPPORTED_COMBINATIONS = [
|
||||||
{"open_source_license": "Not open source"},
|
{"open_source_license": "Not open source"},
|
||||||
{"windows": "y"},
|
{"windows": "y"},
|
||||||
{"windows": "n"},
|
{"windows": "n"},
|
||||||
{"use_pycharm": "y"},
|
{"editor": "None"},
|
||||||
{"use_pycharm": "n"},
|
{"editor": "PyCharm"},
|
||||||
|
{"editor": "VS Code"},
|
||||||
{"use_docker": "y"},
|
{"use_docker": "y"},
|
||||||
{"use_docker": "n"},
|
{"use_docker": "n"},
|
||||||
|
{"postgresql_version": "15"},
|
||||||
{"postgresql_version": "14"},
|
{"postgresql_version": "14"},
|
||||||
{"postgresql_version": "13"},
|
{"postgresql_version": "13"},
|
||||||
{"postgresql_version": "12"},
|
{"postgresql_version": "12"},
|
||||||
|
@ -125,6 +127,7 @@ SUPPORTED_COMBINATIONS = [
|
||||||
{"ci_tool": "Travis"},
|
{"ci_tool": "Travis"},
|
||||||
{"ci_tool": "Gitlab"},
|
{"ci_tool": "Gitlab"},
|
||||||
{"ci_tool": "Github"},
|
{"ci_tool": "Github"},
|
||||||
|
{"ci_tool": "Drone"},
|
||||||
{"keep_local_envs_in_vcs": "y"},
|
{"keep_local_envs_in_vcs": "y"},
|
||||||
{"keep_local_envs_in_vcs": "n"},
|
{"keep_local_envs_in_vcs": "n"},
|
||||||
{"debug": "y"},
|
{"debug": "y"},
|
||||||
|
@ -231,7 +234,7 @@ def test_django_upgrade_passes(cookies, context_override):
|
||||||
try:
|
try:
|
||||||
sh.django_upgrade(
|
sh.django_upgrade(
|
||||||
"--target-version",
|
"--target-version",
|
||||||
"4.1",
|
"4.2",
|
||||||
*python_files,
|
*python_files,
|
||||||
_cwd=str(result.project_path),
|
_cwd=str(result.project_path),
|
||||||
)
|
)
|
||||||
|
@ -239,11 +242,37 @@ def test_django_upgrade_passes(cookies, context_override):
|
||||||
pytest.fail(e.stdout.decode())
|
pytest.fail(e.stdout.decode())
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id)
|
||||||
|
def test_djlint_lint_passes(cookies, context_override):
|
||||||
|
"""Check whether generated project passes djLint --lint."""
|
||||||
|
result = cookies.bake(extra_context=context_override)
|
||||||
|
|
||||||
|
autofixable_rules = "H014,T001"
|
||||||
|
# TODO: remove T002 when fixed https://github.com/Riverside-Healthcare/djLint/issues/687
|
||||||
|
ignored_rules = "H006,H030,H031,T002"
|
||||||
|
try:
|
||||||
|
sh.djlint("--lint", "--ignore", f"{autofixable_rules},{ignored_rules}", ".", _cwd=str(result.project_path))
|
||||||
|
except sh.ErrorReturnCode as e:
|
||||||
|
pytest.fail(e.stdout.decode())
|
||||||
|
|
||||||
|
|
||||||
|
@auto_fixable
|
||||||
|
@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id)
|
||||||
|
def test_djlint_check_passes(cookies, context_override):
|
||||||
|
"""Check whether generated project passes djLint --check."""
|
||||||
|
result = cookies.bake(extra_context=context_override)
|
||||||
|
|
||||||
|
try:
|
||||||
|
sh.djlint("--check", ".", _cwd=str(result.project_path))
|
||||||
|
except sh.ErrorReturnCode as e:
|
||||||
|
pytest.fail(e.stdout.decode())
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
["use_docker", "expected_test_script"],
|
["use_docker", "expected_test_script"],
|
||||||
[
|
[
|
||||||
("n", "pytest"),
|
("n", "pytest"),
|
||||||
("y", "docker-compose -f local.yml run django pytest"),
|
("y", "docker compose -f local.yml run django pytest"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_travis_invokes_pytest(cookies, context, use_docker, expected_test_script):
|
def test_travis_invokes_pytest(cookies, context, use_docker, expected_test_script):
|
||||||
|
@ -268,7 +297,7 @@ def test_travis_invokes_pytest(cookies, context, use_docker, expected_test_scrip
|
||||||
["use_docker", "expected_test_script"],
|
["use_docker", "expected_test_script"],
|
||||||
[
|
[
|
||||||
("n", "pytest"),
|
("n", "pytest"),
|
||||||
("y", "docker-compose -f local.yml run django pytest"),
|
("y", "docker compose -f local.yml run django pytest"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_gitlab_invokes_precommit_and_pytest(cookies, context, use_docker, expected_test_script):
|
def test_gitlab_invokes_precommit_and_pytest(cookies, context, use_docker, expected_test_script):
|
||||||
|
@ -295,7 +324,7 @@ def test_gitlab_invokes_precommit_and_pytest(cookies, context, use_docker, expec
|
||||||
["use_docker", "expected_test_script"],
|
["use_docker", "expected_test_script"],
|
||||||
[
|
[
|
||||||
("n", "pytest"),
|
("n", "pytest"),
|
||||||
("y", "docker-compose -f local.yml run django pytest"),
|
("y", "docker compose -f local.yml run django pytest"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_github_invokes_linter_and_pytest(cookies, context, use_docker, expected_test_script):
|
def test_github_invokes_linter_and_pytest(cookies, context, use_docker, expected_test_script):
|
||||||
|
@ -347,14 +376,15 @@ def test_error_if_incompatible(cookies, context, invalid_context):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
["use_pycharm", "pycharm_docs_exist"],
|
["editor", "pycharm_docs_exist"],
|
||||||
[
|
[
|
||||||
("n", False),
|
("None", False),
|
||||||
("y", True),
|
("PyCharm", True),
|
||||||
|
("VS Code", False),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_pycharm_docs_removed(cookies, context, use_pycharm, pycharm_docs_exist):
|
def test_pycharm_docs_removed(cookies, context, editor, pycharm_docs_exist):
|
||||||
context.update({"use_pycharm": use_pycharm})
|
context.update({"editor": editor})
|
||||||
result = cookies.bake(extra_context=context)
|
result = cookies.bake(extra_context=context)
|
||||||
|
|
||||||
with open(f"{result.project_path}/docs/index.rst") as f:
|
with open(f"{result.project_path}/docs/index.rst") as f:
|
||||||
|
|
|
@ -15,28 +15,28 @@ cookiecutter ../../ --no-input --overwrite-if-exists use_docker=y "$@"
|
||||||
cd my_awesome_project
|
cd my_awesome_project
|
||||||
|
|
||||||
# make sure all images build
|
# make sure all images build
|
||||||
docker-compose -f local.yml build
|
docker compose -f local.yml build
|
||||||
|
|
||||||
# run the project's type checks
|
# run the project's type checks
|
||||||
docker-compose -f local.yml run django mypy my_awesome_project
|
docker compose -f local.yml run django mypy my_awesome_project
|
||||||
|
|
||||||
# run the project's tests
|
# run the project's tests
|
||||||
docker-compose -f local.yml run django pytest
|
docker compose -f local.yml run django pytest
|
||||||
|
|
||||||
# return non-zero status code if there are migrations that have not been created
|
# return non-zero status code if there are migrations that have not been created
|
||||||
docker-compose -f local.yml run django python manage.py makemigrations --dry-run --check || { echo "ERROR: there were changes in the models, but migration listed above have not been created and are not saved in version control"; exit 1; }
|
docker compose -f local.yml run django python manage.py makemigrations --dry-run --check || { echo "ERROR: there were changes in the models, but migration listed above have not been created and are not saved in version control"; exit 1; }
|
||||||
|
|
||||||
# Test support for translations
|
# Test support for translations
|
||||||
docker-compose -f local.yml run django python manage.py makemessages --all
|
docker compose -f local.yml run django python manage.py makemessages --all
|
||||||
|
|
||||||
# Make sure the check doesn't raise any warnings
|
# Make sure the check doesn't raise any warnings
|
||||||
docker-compose -f local.yml run django python manage.py check --fail-level WARNING
|
docker compose -f local.yml run django python manage.py check --fail-level WARNING
|
||||||
|
|
||||||
# Generate the HTML for the documentation
|
# Generate the HTML for the documentation
|
||||||
docker-compose -f local.yml run docs make html
|
docker compose -f local.yml run docs make html
|
||||||
|
|
||||||
# Run npm build script if package.json is present
|
# Run npm build script if package.json is present
|
||||||
if [ -f "package.json" ]
|
if [ -f "package.json" ]
|
||||||
then
|
then
|
||||||
docker-compose -f local.yml run node npm run build
|
docker compose -f local.yml run node npm run build
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#
|
||||||
|
# .bashrc.override.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
# persistent bash history
|
||||||
|
HISTFILE=~/.bash_history
|
||||||
|
PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
|
||||||
|
|
||||||
|
# set some django env vars
|
||||||
|
source /entrypoint
|
||||||
|
|
||||||
|
# restore default shell options
|
||||||
|
set +o errexit
|
||||||
|
set +o pipefail
|
||||||
|
set +o nounset
|
||||||
|
|
||||||
|
# start ssh-agent
|
||||||
|
# https://code.visualstudio.com/docs/remote/troubleshooting
|
||||||
|
eval "$(ssh-agent -s)"
|
|
@ -0,0 +1,87 @@
|
||||||
|
// For format details, see https://containers.dev/implementors/json_reference/
|
||||||
|
{
|
||||||
|
"name": "{{cookiecutter.project_slug}}_dev",
|
||||||
|
"dockerComposeFile": [
|
||||||
|
"../local.yml"
|
||||||
|
],
|
||||||
|
"init": true,
|
||||||
|
"mounts": [
|
||||||
|
{
|
||||||
|
"source": "./.devcontainer/bash_history",
|
||||||
|
"target": "/home/dev-user/.bash_history",
|
||||||
|
"type": "bind"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "/tmp",
|
||||||
|
"target": "/tmp",
|
||||||
|
"type": "bind"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"source": "~/.ssh",
|
||||||
|
"target": "/home/dev-user/.ssh",
|
||||||
|
"type": "bind"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// Tells devcontainer.json supporting services / tools whether they should run
|
||||||
|
// /bin/sh -c "while sleep 1000; do :; done" when starting the container instead of the container’s default command
|
||||||
|
"overrideCommand": false,
|
||||||
|
"service": "django",
|
||||||
|
// "remoteEnv": {"PATH": "/home/dev-user/.local/bin:${containerEnv:PATH}"},
|
||||||
|
"remoteUser": "dev-user",
|
||||||
|
"workspaceFolder": "/app",
|
||||||
|
// Set *default* container specific settings.json values on container create.
|
||||||
|
"customizations": {
|
||||||
|
{%- if cookiecutter.editor == "VS Code" %}
|
||||||
|
"vscode": {
|
||||||
|
"settings": {
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"[python]": {
|
||||||
|
"analysis.autoImportCompletions": true,
|
||||||
|
"analysis.typeCheckingMode": "basic",
|
||||||
|
"defaultInterpreterPath": "/usr/local/bin/python",
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.organizeImports": true
|
||||||
|
},
|
||||||
|
// Uncomment when fixed
|
||||||
|
// https://github.com/microsoft/vscode-remote-release/issues/8474
|
||||||
|
// "editor.defaultFormatter": "ms-python.black-formatter",
|
||||||
|
"formatting.blackPath": "/usr/local/bin/black",
|
||||||
|
"formatting.provider": "black",
|
||||||
|
"languageServer": "Pylance",
|
||||||
|
// "linting.banditPath": "/usr/local/py-utils/bin/bandit",
|
||||||
|
"linting.enabled": true,
|
||||||
|
"linting.flake8Enabled": true,
|
||||||
|
"linting.flake8Path": "/usr/local/bin/flake8",
|
||||||
|
"linting.mypyEnabled": true,
|
||||||
|
"linting.mypyPath": "/usr/local/bin/mypy",
|
||||||
|
"linting.pycodestylePath": "/usr/local/bin/pycodestyle",
|
||||||
|
// "linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
|
||||||
|
"linting.pylintEnabled": true,
|
||||||
|
"linting.pylintPath": "/usr/local/bin/pylint"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_vs-code-specific-properties
|
||||||
|
// Add the IDs of extensions you want installed when the container is created.
|
||||||
|
"extensions": [
|
||||||
|
"davidanson.vscode-markdownlint",
|
||||||
|
"mrmlnc.vscode-duplicate",
|
||||||
|
"visualstudioexptteam.vscodeintellicode",
|
||||||
|
"visualstudioexptteam.intellicode-api-usage-examples",
|
||||||
|
// python
|
||||||
|
"ms-python.python",
|
||||||
|
"ms-python.vscode-pylance",
|
||||||
|
"ms-python.isort",
|
||||||
|
"ms-python.black-formatter",
|
||||||
|
// django
|
||||||
|
"batisteo.vscode-django"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{%- endif %}
|
||||||
|
},
|
||||||
|
// Uncomment the next line if you want start specific services in your Docker Compose config.
|
||||||
|
// "runServices": [],
|
||||||
|
// Uncomment the next line if you want to keep your containers running after VS Code shuts down.
|
||||||
|
// "shutdownAction": "none",
|
||||||
|
// Uncomment the next line to run commands after the container is created.
|
||||||
|
"postCreateCommand": "cat .devcontainer/bashrc.override.sh >> ~/.bashrc"
|
||||||
|
}
|
|
@ -9,3 +9,4 @@
|
||||||
.travis.yml
|
.travis.yml
|
||||||
venv
|
venv
|
||||||
.git
|
.git
|
||||||
|
.envs/
|
||||||
|
|
48
{{cookiecutter.project_slug}}/.drone.yml
Normal file
48
{{cookiecutter.project_slug}}/.drone.yml
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
kind: pipeline
|
||||||
|
name: default
|
||||||
|
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: '{{ cookiecutter.project_slug }}'
|
||||||
|
POSTGRES_PASSWORD: ''
|
||||||
|
POSTGRES_DB: 'test_{{ cookiecutter.project_slug }}'
|
||||||
|
POSTGRES_HOST_AUTH_METHOD: trust
|
||||||
|
{%- if cookiecutter.use_celery == 'y' %}
|
||||||
|
CELERY_BROKER_URL: 'redis://redis:6379/0'
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: lint
|
||||||
|
pull: if-not-exists
|
||||||
|
image: python:3.11
|
||||||
|
environment:
|
||||||
|
PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
|
||||||
|
volumes:
|
||||||
|
- name: pre-commit cache
|
||||||
|
path: ${PRE_COMMIT_HOME}
|
||||||
|
commands:
|
||||||
|
- export PRE_COMMIT_HOME=$CI_PROJECT_DIR/.cache/pre-commit
|
||||||
|
- pip install -q pre-commit
|
||||||
|
- pre-commit run --show-diff-on-failure --color=always --all-files
|
||||||
|
|
||||||
|
- name: test
|
||||||
|
pull: if-not-exists
|
||||||
|
{%- if cookiecutter.use_docker == 'y' %}
|
||||||
|
image: docker/compose:1.29.2
|
||||||
|
environment:
|
||||||
|
DATABASE_URL: pgsql://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres/$POSTGRES_DB
|
||||||
|
commands:
|
||||||
|
- docker-compose -f local.yml build
|
||||||
|
- docker-compose -f local.yml run --rm django python manage.py migrate
|
||||||
|
- docker-compose -f local.yml up -d
|
||||||
|
- docker-compose -f local.yml run django pytest
|
||||||
|
{%- else %}
|
||||||
|
image: python:3.11
|
||||||
|
commands:
|
||||||
|
- pip install -r requirements/local.txt
|
||||||
|
- pytest
|
||||||
|
{%- endif%}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: pre-commit cache
|
||||||
|
host:
|
||||||
|
path: /tmp/drone/cache/pre-commit
|
|
@ -49,7 +49,7 @@ jobs:
|
||||||
- 6379:6379
|
- 6379:6379
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:12
|
image: postgres:{{ cookiecutter.postgresql_version }}
|
||||||
ports:
|
ports:
|
||||||
- 5432:5432
|
- 5432:5432
|
||||||
env:
|
env:
|
||||||
|
@ -69,16 +69,16 @@ jobs:
|
||||||
{%- if cookiecutter.use_docker == 'y' %}
|
{%- if cookiecutter.use_docker == 'y' %}
|
||||||
|
|
||||||
- name: Build the Stack
|
- name: Build the Stack
|
||||||
run: docker-compose -f local.yml build
|
run: docker compose -f local.yml build
|
||||||
|
|
||||||
- name: Run DB Migrations
|
- name: Run DB Migrations
|
||||||
run: docker-compose -f local.yml run --rm django python manage.py migrate
|
run: docker compose -f local.yml run --rm django python manage.py migrate
|
||||||
|
|
||||||
- name: Run Django Tests
|
- name: Run Django Tests
|
||||||
run: docker-compose -f local.yml run django pytest
|
run: docker compose -f local.yml run django pytest
|
||||||
|
|
||||||
- name: Tear down the Stack
|
- name: Tear down the Stack
|
||||||
run: docker-compose -f local.yml down
|
run: docker compose -f local.yml down
|
||||||
{%- else %}
|
{%- else %}
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
|
|
7
{{cookiecutter.project_slug}}/.gitignore
vendored
7
{{cookiecutter.project_slug}}/.gitignore
vendored
|
@ -161,11 +161,10 @@ typings/
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
|
|
||||||
# Local History for Visual Studio Code
|
# Local History for devcontainer
|
||||||
.history/
|
.devcontainer/bash_history
|
||||||
|
|
||||||
|
{% if cookiecutter.editor == 'PyCharm' -%}
|
||||||
{% if cookiecutter.use_pycharm == 'y' -%}
|
|
||||||
# Provided default Pycharm Run/Debug Configurations should be tracked by git
|
# Provided default Pycharm Run/Debug Configurations should be tracked by git
|
||||||
# In case of local modifications made by Pycharm, use update-index command
|
# In case of local modifications made by Pycharm, use update-index command
|
||||||
# for each changed file, like this:
|
# for each changed file, like this:
|
||||||
|
|
|
@ -33,12 +33,12 @@ pytest:
|
||||||
services:
|
services:
|
||||||
- docker:dind
|
- docker:dind
|
||||||
before_script:
|
before_script:
|
||||||
- docker-compose -f local.yml build
|
- docker compose -f local.yml build
|
||||||
# Ensure celerybeat does not crash due to non-existent tables
|
# Ensure celerybeat does not crash due to non-existent tables
|
||||||
- docker-compose -f local.yml run --rm django python manage.py migrate
|
- docker compose -f local.yml run --rm django python manage.py migrate
|
||||||
- docker-compose -f local.yml up -d
|
- docker compose -f local.yml up -d
|
||||||
script:
|
script:
|
||||||
- docker-compose -f local.yml run django pytest
|
- docker compose -f local.yml run django pytest
|
||||||
{%- else %}
|
{%- else %}
|
||||||
image: python:3.11
|
image: python:3.11
|
||||||
tags:
|
tags:
|
||||||
|
|
|
@ -18,26 +18,26 @@ repos:
|
||||||
- id: detect-private-key
|
- id: detect-private-key
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||||
rev: v3.0.0-alpha.9-for-vscode
|
rev: v3.0.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: prettier
|
- id: prettier
|
||||||
args: ['--tab-width', '2', '--single-quote']
|
args: ['--tab-width', '2', '--single-quote']
|
||||||
exclude: '{{cookiecutter.project_slug}}/templates/'
|
exclude: '{{cookiecutter.project_slug}}/templates/'
|
||||||
|
|
||||||
- repo: https://github.com/adamchainz/django-upgrade
|
- repo: https://github.com/adamchainz/django-upgrade
|
||||||
rev: '1.13.0'
|
rev: '1.14.0'
|
||||||
hooks:
|
hooks:
|
||||||
- id: django-upgrade
|
- id: django-upgrade
|
||||||
args: ['--target-version', '4.1']
|
args: ['--target-version', '4.2']
|
||||||
|
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
rev: v3.4.0
|
rev: v3.10.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
args: [--py311-plus]
|
args: [--py311-plus]
|
||||||
|
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 23.3.0
|
rev: 23.7.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
|
|
||||||
|
@ -47,10 +47,16 @@ repos:
|
||||||
- id: isort
|
- id: isort
|
||||||
|
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 6.0.0
|
rev: 6.1.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
|
|
||||||
|
- repo: https://github.com/Riverside-Healthcare/djLint
|
||||||
|
rev: v1.32.1
|
||||||
|
hooks:
|
||||||
|
- id: djlint-reformat-django
|
||||||
|
- id: djlint-django
|
||||||
|
|
||||||
# sets up .pre-commit-ci.yaml to ensure pre-commit dependencies stay up to date
|
# sets up .pre-commit-ci.yaml to ensure pre-commit dependencies stay up to date
|
||||||
ci:
|
ci:
|
||||||
autoupdate_schedule: weekly
|
autoupdate_schedule: weekly
|
||||||
|
|
|
@ -17,16 +17,16 @@ jobs:
|
||||||
- name: "Django Test"
|
- name: "Django Test"
|
||||||
{%- if cookiecutter.use_docker == 'y' %}
|
{%- if cookiecutter.use_docker == 'y' %}
|
||||||
before_script:
|
before_script:
|
||||||
- docker-compose -v
|
- docker compose -v
|
||||||
- docker -v
|
- docker -v
|
||||||
- docker-compose -f local.yml build
|
- docker compose -f local.yml build
|
||||||
# Ensure celerybeat does not crash due to non-existent tables
|
# Ensure celerybeat does not crash due to non-existent tables
|
||||||
- docker-compose -f local.yml run --rm django python manage.py migrate
|
- docker compose -f local.yml run --rm django python manage.py migrate
|
||||||
- docker-compose -f local.yml up -d
|
- docker compose -f local.yml up -d
|
||||||
script:
|
script:
|
||||||
- "docker-compose -f local.yml run django pytest"
|
- "docker compose -f local.yml run django pytest"
|
||||||
after_failure:
|
after_failure:
|
||||||
- docker-compose -f local.yml logs
|
- docker compose -f local.yml logs
|
||||||
{%- else %}
|
{%- else %}
|
||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
{%- if cookiecutter.frontend_pipeline == "Django Compressor" %}
|
||||||
|
|
||||||
compress_enabled() {
|
compress_enabled() {
|
||||||
python << END
|
python << END
|
||||||
|
@ -19,4 +20,7 @@ if compress_enabled
|
||||||
then
|
then
|
||||||
python manage.py compress
|
python manage.py compress
|
||||||
fi
|
fi
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
python manage.py collectstatic --noinput
|
python manage.py collectstatic --noinput
|
||||||
|
python manage.py compilemessages -i site-packages
|
||||||
|
|
|
@ -33,6 +33,18 @@ ENV BUILD_ENV ${BUILD_ENVIRONMENT}
|
||||||
|
|
||||||
WORKDIR ${APP_HOME}
|
WORKDIR ${APP_HOME}
|
||||||
|
|
||||||
|
{% if cookiecutter.use_docker == "y" %}
|
||||||
|
# devcontainer dependencies and utils
|
||||||
|
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||||
|
sudo git bash-completion nano ssh
|
||||||
|
|
||||||
|
# Create devcontainer user and add it to sudoers
|
||||||
|
RUN groupadd --gid 1000 dev-user \
|
||||||
|
&& useradd --uid 1000 --gid dev-user --shell /bin/bash --create-home dev-user \
|
||||||
|
&& echo dev-user ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/dev-user \
|
||||||
|
&& chmod 0440 /etc/sudoers.d/dev-user
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
# Install required system dependencies
|
# Install required system dependencies
|
||||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||||
# psycopg2 dependencies
|
# psycopg2 dependencies
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
### Download a file from your Amazon S3 bucket to the postgres /backups folder
|
### Download a file from your Amazon S3 bucket to the postgres /backups folder
|
||||||
###
|
###
|
||||||
### Usage:
|
### Usage:
|
||||||
### $ docker-compose -f production.yml run --rm awscli <1>
|
### $ docker compose -f production.yml run --rm awscli <1>
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
### Upload the /backups folder to Amazon S3
|
### Upload the /backups folder to Amazon S3
|
||||||
###
|
###
|
||||||
### Usage:
|
### Usage:
|
||||||
### $ docker-compose -f production.yml run --rm awscli upload
|
### $ docker compose -f production.yml run --rm awscli upload
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
|
@ -121,4 +121,11 @@ RUN chown django:django ${APP_HOME}
|
||||||
|
|
||||||
USER django
|
USER django
|
||||||
|
|
||||||
|
RUN DATABASE_URL="" \
|
||||||
|
{%- if cookiecutter.use_celery == "y" %}
|
||||||
|
CELERY_BROKER_URL="" \
|
||||||
|
{%- endif %}
|
||||||
|
DJANGO_SETTINGS_MODULE="config.settings.test" \
|
||||||
|
python manage.py compilemessages
|
||||||
|
|
||||||
ENTRYPOINT ["/entrypoint"]
|
ENTRYPOINT ["/entrypoint"]
|
||||||
|
|
|
@ -20,14 +20,14 @@ python << END
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import psycopg2
|
import psycopg
|
||||||
|
|
||||||
suggest_unrecoverable_after = 30
|
suggest_unrecoverable_after = 30
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
psycopg2.connect(
|
psycopg.connect(
|
||||||
dbname="${POSTGRES_DB}",
|
dbname="${POSTGRES_DB}",
|
||||||
user="${POSTGRES_USER}",
|
user="${POSTGRES_USER}",
|
||||||
password="${POSTGRES_PASSWORD}",
|
password="${POSTGRES_PASSWORD}",
|
||||||
|
@ -35,7 +35,7 @@ while True:
|
||||||
port="${POSTGRES_PORT}",
|
port="${POSTGRES_PORT}",
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
except psycopg2.OperationalError as error:
|
except psycopg.OperationalError as error:
|
||||||
sys.stderr.write("Waiting for PostgreSQL to become available...\n")
|
sys.stderr.write("Waiting for PostgreSQL to become available...\n")
|
||||||
|
|
||||||
if time.time() - start > suggest_unrecoverable_after:
|
if time.time() - start > suggest_unrecoverable_after:
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
### Create a database backup.
|
### Create a database backup.
|
||||||
###
|
###
|
||||||
### Usage:
|
### Usage:
|
||||||
### $ docker-compose -f <environment>.yml (exec |run --rm) postgres backup
|
### $ docker compose -f <environment>.yml (exec |run --rm) postgres backup
|
||||||
|
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
### View backups.
|
### View backups.
|
||||||
###
|
###
|
||||||
### Usage:
|
### Usage:
|
||||||
### $ docker-compose -f <environment>.yml (exec |run --rm) postgres backups
|
### $ docker compose -f <environment>.yml (exec |run --rm) postgres backups
|
||||||
|
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
### <1> filename of an existing backup.
|
### <1> filename of an existing backup.
|
||||||
###
|
###
|
||||||
### Usage:
|
### Usage:
|
||||||
### $ docker-compose -f <environment>.yml (exec |run --rm) postgres restore <1>
|
### $ docker compose -f <environment>.yml (exec |run --rm) postgres restore <1>
|
||||||
|
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM traefik:2.10.1
|
FROM traefik:2.10.4
|
||||||
RUN mkdir -p /etc/traefik/acme \
|
RUN mkdir -p /etc/traefik/acme \
|
||||||
&& touch /etc/traefik/acme/acme.json \
|
&& touch /etc/traefik/acme/acme.json \
|
||||||
&& chmod 600 /etc/traefik/acme/acme.json
|
&& chmod 600 /etc/traefik/acme/acme.json
|
||||||
|
|
|
@ -250,6 +250,9 @@ ADMIN_URL = "admin/"
|
||||||
ADMINS = [("""{{cookiecutter.author_name}}""", "{{cookiecutter.email}}")]
|
ADMINS = [("""{{cookiecutter.author_name}}""", "{{cookiecutter.email}}")]
|
||||||
# https://docs.djangoproject.com/en/dev/ref/settings/#managers
|
# https://docs.djangoproject.com/en/dev/ref/settings/#managers
|
||||||
MANAGERS = ADMINS
|
MANAGERS = ADMINS
|
||||||
|
# https://cookiecutter-django.readthedocs.io/en/latest/settings.html#other-environment-settings
|
||||||
|
# Force the `admin` sign in process to go through the `django-allauth` workflow
|
||||||
|
DJANGO_ADMIN_FORCE_ALLAUTH = env.bool("DJANGO_ADMIN_FORCE_ALLAUTH", default=False)
|
||||||
|
|
||||||
# LOGGING
|
# LOGGING
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -146,7 +146,7 @@ SERVER_EMAIL = env("DJANGO_SERVER_EMAIL", default=DEFAULT_FROM_EMAIL)
|
||||||
# https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix
|
# https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix
|
||||||
EMAIL_SUBJECT_PREFIX = env(
|
EMAIL_SUBJECT_PREFIX = env(
|
||||||
"DJANGO_EMAIL_SUBJECT_PREFIX",
|
"DJANGO_EMAIL_SUBJECT_PREFIX",
|
||||||
default="[{{cookiecutter.project_name}}]",
|
default="[{{cookiecutter.project_name}}] ",
|
||||||
)
|
)
|
||||||
|
|
||||||
# ADMIN
|
# ADMIN
|
||||||
|
|
|
@ -15,7 +15,7 @@ from inside the `{{cookiecutter.project_slug}}/docs` directory.
|
||||||
{% else %}
|
{% else %}
|
||||||
To build and serve docs, use the commands::
|
To build and serve docs, use the commands::
|
||||||
|
|
||||||
docker-compose -f local.yml up docs
|
docker compose -f local.yml up docs
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ Welcome to {{ cookiecutter.project_name }}'s documentation!
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
:caption: Contents:
|
:caption: Contents:
|
||||||
|
|
||||||
howto{% if cookiecutter.use_pycharm == 'y' %}
|
howto{% if cookiecutter.editor == 'PyCharm' %}
|
||||||
pycharm/configuration{% endif %}
|
pycharm/configuration{% endif %}
|
||||||
users
|
users
|
||||||
|
|
||||||
|
|
32
{{cookiecutter.project_slug}}/locale/README.md
Normal file
32
{{cookiecutter.project_slug}}/locale/README.md
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# Translations
|
||||||
|
|
||||||
|
Start by configuring the `LANGUAGES` settings in `base.py`, by uncommenting languages you are willing to support. Then, translations strings will be placed in this folder when running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
{% if cookiecutter.use_docker == 'y' %}docker compose -f local.yml run --rm django {% endif %}python manage.py makemessages -all --no-location
|
||||||
|
```
|
||||||
|
|
||||||
|
This should generate `django.po` (stands for Portable Object) files under each locale `<locale name>/LC_MESSAGES/django.po`. Each translatable string in the codebase is collected with its `msgid` and need to be translated as `msgstr`, for example:
|
||||||
|
|
||||||
|
```po
|
||||||
|
msgid "users"
|
||||||
|
msgstr "utilisateurs"
|
||||||
|
```
|
||||||
|
|
||||||
|
Once all translations are done, they need to be compiled into `.mo` files (stands for Machine Object), which are the actual binary files used by the application:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
{% if cookiecutter.use_docker == 'y' %}docker compose -f local.yml run --rm django {% endif %}python manage.py compilemessages
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the `.po` files are NOT used by the application directly, so if the `.mo` files are out of dates, the content won't appear as translated even if the `.po` files are up-to-date.
|
||||||
|
|
||||||
|
## Production
|
||||||
|
|
||||||
|
The production image runs `compilemessages` automatically at build time, so as long as your translated source files (PO) are up-to-date, you're good to go.
|
||||||
|
|
||||||
|
## Add a new language
|
||||||
|
|
||||||
|
1. Update the [`LANGUAGES` setting](https://docs.djangoproject.com/en/stable/ref/settings/#std-setting-LANGUAGES) to your project's base settings.
|
||||||
|
2. Create the locale folder for the language next to this file, e.g. `fr_FR` for French. Make sure the case is correct.
|
||||||
|
3. Run `makemessages` (as instructed above) to generate the PO files for the new language.
|
|
@ -1,14 +0,0 @@
|
||||||
Translations
|
|
||||||
============
|
|
||||||
|
|
||||||
Start by configuring `LANGUAGES` at settings, by uncommenting languages you are willing to support.
|
|
||||||
|
|
||||||
Translations will be placed in this folder when running:
|
|
||||||
|
|
||||||
python manage.py makemessages --all
|
|
||||||
|
|
||||||
Then you should edit the .po files providing proper translations and then run the following for compiling the messages:
|
|
||||||
|
|
||||||
python manage.py compilemessages
|
|
||||||
|
|
||||||
Note: You may need to restart the django server for changes to take effect.
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Translations for the {{ cookiecutter.project_name }} project
|
||||||
|
# Copyright (C) {% now 'utc', '%Y' %} {{ cookiecutter.author_name }}
|
||||||
|
# {{ cookiecutter.author_name }} <{{ cookiecutter.email }}>, {% now 'utc', '%Y' %}.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: {{ cookiecutter.version }}\n"
|
||||||
|
"Language: en-US\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
|
@ -1,18 +1,12 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
# Translations for the {{ cookiecutter.project_name }} project
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
# Copyright (C) {% now 'utc', '%Y' %} {{ cookiecutter.author_name }}
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
# {{ cookiecutter.author_name }} <{{ cookiecutter.email }}>, {% now 'utc', '%Y' %}.
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: {{ cookiecutter.version }}\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Language: pt-BR\n"
|
||||||
"POT-Creation-Date: 2023-06-04 21:42+0000\n"
|
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
||||||
"Language: \n"
|
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
@ -133,7 +127,7 @@ msgstr "Ou, <a href=\"%(signup_url)s\">cadastre-se</a> para uma conta em %(site_
|
||||||
|
|
||||||
#: {{cookiecutter.project_slug}}/templates/account/login.html:32
|
#: {{cookiecutter.project_slug}}/templates/account/login.html:32
|
||||||
msgid "or"
|
msgid "or"
|
||||||
msgstr "or"
|
msgstr "ou"
|
||||||
|
|
||||||
#: {{cookiecutter.project_slug}}/templates/account/login.html:41
|
#: {{cookiecutter.project_slug}}/templates/account/login.html:41
|
||||||
#, python-format
|
#, python-format
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
"pixrem": "^5.0.0",
|
"pixrem": "^5.0.0",
|
||||||
"postcss": "^8.3.11",
|
"postcss": "^8.3.11",
|
||||||
"postcss-loader": "^7.0.2",
|
"postcss-loader": "^7.0.2",
|
||||||
"postcss-preset-env": "^8.0.1",
|
"postcss-preset-env": "^9.0.0",
|
||||||
"sass": "^1.43.4",
|
"sass": "^1.43.4",
|
||||||
"sass-loader": "^13.2.0",
|
"sass-loader": "^13.2.0",
|
||||||
"webpack": "^5.65.0",
|
"webpack": "^5.65.0",
|
||||||
|
|
|
@ -90,3 +90,23 @@ generated-members = [
|
||||||
"save",
|
"save",
|
||||||
"delete",
|
"delete",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# ==== djLint ====
|
||||||
|
[tool.djlint]
|
||||||
|
blank_line_after_tag = "load,extends"
|
||||||
|
close_void_tags = true
|
||||||
|
format_css = true
|
||||||
|
format_js = true
|
||||||
|
# TODO: remove T002 when fixed https://github.com/Riverside-Healthcare/djLint/issues/687
|
||||||
|
ignore = "H006,H030,H031,T002"
|
||||||
|
include = "H017,H035"
|
||||||
|
indent = 2
|
||||||
|
max_line_length = 119
|
||||||
|
profile = "django"
|
||||||
|
|
||||||
|
[tool.djlint.css]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[tool.djlint.js]
|
||||||
|
indent_size = 2
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
python-slugify==8.0.1 # https://github.com/un33k/python-slugify
|
python-slugify==8.0.1 # https://github.com/un33k/python-slugify
|
||||||
Pillow==9.5.0 # https://github.com/python-pillow/Pillow
|
Pillow==10.0.0 # https://github.com/python-pillow/Pillow
|
||||||
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
|
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
|
||||||
{%- if cookiecutter.windows == 'y' and cookiecutter.use_docker == 'n' %}
|
{%- if cookiecutter.windows == 'y' and cookiecutter.use_docker == 'n' %}
|
||||||
rcssmin==1.1.0 --install-option="--without-c-extensions" # https://github.com/ndparker/rcssmin
|
rcssmin==1.1.0 --install-option="--without-c-extensions" # https://github.com/ndparker/rcssmin
|
||||||
|
@ -9,42 +9,42 @@ rcssmin==1.1.1 # https://github.com/ndparker/rcssmin
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
argon2-cffi==21.3.0 # https://github.com/hynek/argon2_cffi
|
argon2-cffi==21.3.0 # https://github.com/hynek/argon2_cffi
|
||||||
{%- if cookiecutter.use_whitenoise == 'y' %}
|
{%- if cookiecutter.use_whitenoise == 'y' %}
|
||||||
whitenoise==6.4.0 # https://github.com/evansd/whitenoise
|
whitenoise==6.5.0 # https://github.com/evansd/whitenoise
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
redis==4.5.5 # https://github.com/redis/redis-py
|
redis==4.6.0 # https://github.com/redis/redis-py
|
||||||
{%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %}
|
{%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %}
|
||||||
hiredis==2.2.3 # https://github.com/redis/hiredis-py
|
hiredis==2.2.3 # https://github.com/redis/hiredis-py
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- if cookiecutter.use_celery == "y" %}
|
{%- if cookiecutter.use_celery == "y" %}
|
||||||
celery==5.3.0 # pyup: < 6.0 # https://github.com/celery/celery
|
celery==5.3.1 # pyup: < 6.0 # https://github.com/celery/celery
|
||||||
django-celery-beat==2.5.0 # https://github.com/celery/django-celery-beat
|
django-celery-beat==2.5.0 # https://github.com/celery/django-celery-beat
|
||||||
{%- if cookiecutter.use_docker == 'y' %}
|
{%- if cookiecutter.use_docker == 'y' %}
|
||||||
flower==1.2.0 # https://github.com/mher/flower
|
flower==2.0.1 # https://github.com/mher/flower
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- if cookiecutter.use_async == 'y' %}
|
{%- if cookiecutter.use_async == 'y' %}
|
||||||
uvicorn[standard]==0.22.0 # https://github.com/encode/uvicorn
|
uvicorn[standard]==0.23.2 # https://github.com/encode/uvicorn
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
django==4.1.9 # pyup: < 4.2 # https://www.djangoproject.com/
|
django==4.2.4 # pyup: < 5.0 # https://www.djangoproject.com/
|
||||||
django-environ==0.10.0 # https://github.com/joke2k/django-environ
|
django-environ==0.10.0 # https://github.com/joke2k/django-environ
|
||||||
django-model-utils==4.3.1 # https://github.com/jazzband/django-model-utils
|
django-model-utils==4.3.1 # https://github.com/jazzband/django-model-utils
|
||||||
django-allauth==0.54.0 # https://github.com/pennersr/django-allauth
|
django-allauth==0.54.0 # https://github.com/pennersr/django-allauth
|
||||||
django-crispy-forms==2.0 # https://github.com/django-crispy-forms/django-crispy-forms
|
django-crispy-forms==2.0 # https://github.com/django-crispy-forms/django-crispy-forms
|
||||||
crispy-bootstrap5==0.7 # https://github.com/django-crispy-forms/crispy-bootstrap5
|
crispy-bootstrap5==0.7 # https://github.com/django-crispy-forms/crispy-bootstrap5
|
||||||
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
|
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
|
||||||
django-compressor==4.3.1 # https://github.com/django-compressor/django-compressor
|
django-compressor==4.4 # https://github.com/django-compressor/django-compressor
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
django-redis==5.2.0 # https://github.com/jazzband/django-redis
|
django-redis==5.3.0 # https://github.com/jazzband/django-redis
|
||||||
{%- if cookiecutter.use_drf == 'y' %}
|
{%- if cookiecutter.use_drf == 'y' %}
|
||||||
# Django REST Framework
|
# Django REST Framework
|
||||||
djangorestframework==3.14.0 # https://github.com/encode/django-rest-framework
|
djangorestframework==3.14.0 # https://github.com/encode/django-rest-framework
|
||||||
django-cors-headers==4.0.0 # https://github.com/adamchainz/django-cors-headers
|
django-cors-headers==4.2.0 # https://github.com/adamchainz/django-cors-headers
|
||||||
# DRF-spectacular for api documentation
|
# DRF-spectacular for api documentation
|
||||||
drf-spectacular==0.26.2 # https://github.com/tfranzel/drf-spectacular
|
drf-spectacular==0.26.4 # https://github.com/tfranzel/drf-spectacular
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- if cookiecutter.frontend_pipeline == 'Webpack' %}
|
{%- if cookiecutter.frontend_pipeline == 'Webpack' %}
|
||||||
django-webpack-loader==2.0.0 # https://github.com/django-webpack/django-webpack-loader
|
django-webpack-loader==2.0.1 # https://github.com/django-webpack/django-webpack-loader
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
-r base.txt
|
-r base.txt
|
||||||
|
|
||||||
Werkzeug[watchdog]==2.3.5 # https://github.com/pallets/werkzeug
|
Werkzeug[watchdog]==2.3.6 # https://github.com/pallets/werkzeug
|
||||||
ipdb==0.13.13 # https://github.com/gotcha/ipdb
|
ipdb==0.13.13 # https://github.com/gotcha/ipdb
|
||||||
{%- if cookiecutter.use_docker == 'y' %}
|
{%- if cookiecutter.use_docker == 'y' %}
|
||||||
psycopg2==2.9.6 # https://github.com/psycopg/psycopg2
|
psycopg[c]==3.1.9 # https://github.com/psycopg/psycopg
|
||||||
{%- else %}
|
{%- else %}
|
||||||
psycopg2-binary==2.9.6 # https://github.com/psycopg/psycopg2
|
psycopg[binary]==3.1.9 # https://github.com/psycopg/psycopg
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- if cookiecutter.use_async == 'y' or cookiecutter.use_celery == 'y' %}
|
{%- if cookiecutter.use_async == 'y' or cookiecutter.use_celery == 'y' %}
|
||||||
watchfiles==0.19.0 # https://github.com/samuelcolvin/watchfiles
|
watchfiles==0.19.0 # https://github.com/samuelcolvin/watchfiles
|
||||||
|
@ -13,12 +13,12 @@ watchfiles==0.19.0 # https://github.com/samuelcolvin/watchfiles
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
mypy==1.3.0 # https://github.com/python/mypy
|
mypy==1.4.1 # https://github.com/python/mypy
|
||||||
django-stubs[compatible-mypy]==4.2.1 # https://github.com/typeddjango/django-stubs
|
django-stubs[compatible-mypy]==4.2.3 # https://github.com/typeddjango/django-stubs
|
||||||
pytest==7.3.1 # https://github.com/pytest-dev/pytest
|
pytest==7.4.0 # https://github.com/pytest-dev/pytest
|
||||||
pytest-sugar==0.9.7 # https://github.com/Frozenball/pytest-sugar
|
pytest-sugar==0.9.7 # https://github.com/Frozenball/pytest-sugar
|
||||||
{%- if cookiecutter.use_drf == "y" %}
|
{%- if cookiecutter.use_drf == "y" %}
|
||||||
djangorestframework-stubs[compatible-mypy]==3.14.1 # https://github.com/typeddjango/djangorestframework-stubs
|
djangorestframework-stubs[compatible-mypy]==3.14.2 # https://github.com/typeddjango/djangorestframework-stubs
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
|
@ -28,21 +28,22 @@ sphinx-autobuild==2021.3.14 # https://github.com/GaretJax/sphinx-autobuild
|
||||||
|
|
||||||
# Code quality
|
# Code quality
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
flake8==6.0.0 # https://github.com/PyCQA/flake8
|
flake8==6.1.0 # https://github.com/PyCQA/flake8
|
||||||
flake8-isort==6.0.0 # https://github.com/gforcada/flake8-isort
|
flake8-isort==6.0.0 # https://github.com/gforcada/flake8-isort
|
||||||
coverage==7.2.7 # https://github.com/nedbat/coveragepy
|
coverage==7.3.0 # https://github.com/nedbat/coveragepy
|
||||||
black==23.3.0 # https://github.com/psf/black
|
black==23.7.0 # https://github.com/psf/black
|
||||||
|
djlint==1.32.1 # https://github.com/Riverside-Healthcare/djLint
|
||||||
pylint-django==2.5.3 # https://github.com/PyCQA/pylint-django
|
pylint-django==2.5.3 # https://github.com/PyCQA/pylint-django
|
||||||
{%- if cookiecutter.use_celery == 'y' %}
|
{%- if cookiecutter.use_celery == 'y' %}
|
||||||
pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery
|
pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
pre-commit==3.3.2 # https://github.com/pre-commit/pre-commit
|
pre-commit==3.3.3 # https://github.com/pre-commit/pre-commit
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
factory-boy==3.2.1 # https://github.com/FactoryBoy/factory_boy
|
factory-boy==3.3.0 # https://github.com/FactoryBoy/factory_boy
|
||||||
|
|
||||||
django-debug-toolbar==4.1.0 # https://github.com/jazzband/django-debug-toolbar
|
django-debug-toolbar==4.2.0 # https://github.com/jazzband/django-debug-toolbar
|
||||||
django-extensions==3.2.3 # https://github.com/django-extensions/django-extensions
|
django-extensions==3.2.3 # https://github.com/django-extensions/django-extensions
|
||||||
django-coverage-plugin==3.0.0 # https://github.com/nedbat/django_coverage_plugin
|
django-coverage-plugin==3.1.0 # https://github.com/nedbat/django_coverage_plugin
|
||||||
pytest-django==4.5.2 # https://github.com/pytest-dev/pytest-django
|
pytest-django==4.5.2 # https://github.com/pytest-dev/pytest-django
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
-r base.txt
|
-r base.txt
|
||||||
|
|
||||||
gunicorn==20.1.0 # https://github.com/benoitc/gunicorn
|
gunicorn==21.2.0 # https://github.com/benoitc/gunicorn
|
||||||
psycopg2==2.9.6 # https://github.com/psycopg/psycopg2
|
psycopg[c]==3.1.9 # https://github.com/psycopg/psycopg
|
||||||
{%- if cookiecutter.use_whitenoise == 'n' %}
|
{%- if cookiecutter.use_whitenoise == 'n' %}
|
||||||
Collectfast==2.2.0 # https://github.com/antonagestam/collectfast
|
Collectfast==2.2.0 # https://github.com/antonagestam/collectfast
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- if cookiecutter.use_sentry == "y" %}
|
{%- if cookiecutter.use_sentry == "y" %}
|
||||||
sentry-sdk==1.25.1 # https://github.com/getsentry/sentry-python
|
sentry-sdk==1.29.2 # https://github.com/getsentry/sentry-python
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- if cookiecutter.use_docker == "n" and cookiecutter.windows == "y" %}
|
{%- if cookiecutter.use_docker == "n" and cookiecutter.windows == "y" %}
|
||||||
hiredis==2.2.3 # https://github.com/redis/hiredis-py
|
hiredis==2.2.3 # https://github.com/redis/hiredis-py
|
||||||
|
@ -24,21 +24,21 @@ django-storages[google]==1.13.2 # https://github.com/jschneier/django-storages
|
||||||
django-storages[azure]==1.13.2 # https://github.com/jschneier/django-storages
|
django-storages[azure]==1.13.2 # https://github.com/jschneier/django-storages
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- if cookiecutter.mail_service == 'Mailgun' %}
|
{%- if cookiecutter.mail_service == 'Mailgun' %}
|
||||||
django-anymail[mailgun]==10.0 # https://github.com/anymail/django-anymail
|
django-anymail[mailgun]==10.1 # https://github.com/anymail/django-anymail
|
||||||
{%- elif cookiecutter.mail_service == 'Amazon SES' %}
|
{%- elif cookiecutter.mail_service == 'Amazon SES' %}
|
||||||
django-anymail[amazon-ses]==10.0 # https://github.com/anymail/django-anymail
|
django-anymail[amazon-ses]==10.1 # https://github.com/anymail/django-anymail
|
||||||
{%- elif cookiecutter.mail_service == 'Mailjet' %}
|
{%- elif cookiecutter.mail_service == 'Mailjet' %}
|
||||||
django-anymail[mailjet]==10.0 # https://github.com/anymail/django-anymail
|
django-anymail[mailjet]==10.1 # https://github.com/anymail/django-anymail
|
||||||
{%- elif cookiecutter.mail_service == 'Mandrill' %}
|
{%- elif cookiecutter.mail_service == 'Mandrill' %}
|
||||||
django-anymail[mandrill]==10.0 # https://github.com/anymail/django-anymail
|
django-anymail[mandrill]==10.1 # https://github.com/anymail/django-anymail
|
||||||
{%- elif cookiecutter.mail_service == 'Postmark' %}
|
{%- elif cookiecutter.mail_service == 'Postmark' %}
|
||||||
django-anymail[postmark]==10.0 # https://github.com/anymail/django-anymail
|
django-anymail[postmark]==10.1 # https://github.com/anymail/django-anymail
|
||||||
{%- elif cookiecutter.mail_service == 'Sendgrid' %}
|
{%- elif cookiecutter.mail_service == 'Sendgrid' %}
|
||||||
django-anymail[sendgrid]==10.0 # https://github.com/anymail/django-anymail
|
django-anymail[sendgrid]==10.1 # https://github.com/anymail/django-anymail
|
||||||
{%- elif cookiecutter.mail_service == 'SendinBlue' %}
|
{%- elif cookiecutter.mail_service == 'SendinBlue' %}
|
||||||
django-anymail[sendinblue]==10.0 # https://github.com/anymail/django-anymail
|
django-anymail[sendinblue]==10.1 # https://github.com/anymail/django-anymail
|
||||||
{%- elif cookiecutter.mail_service == 'SparkPost' %}
|
{%- elif cookiecutter.mail_service == 'SparkPost' %}
|
||||||
django-anymail[sparkpost]==10.0 # https://github.com/anymail/django-anymail
|
django-anymail[sparkpost]==10.1 # https://github.com/anymail/django-anymail
|
||||||
{%- elif cookiecutter.mail_service == 'Other SMTP' %}
|
{%- elif cookiecutter.mail_service == 'Other SMTP' %}
|
||||||
django-anymail==10.0 # https://github.com/anymail/django-anymail
|
django-anymail==10.1 # https://github.com/anymail/django-anymail
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
{% raw %}{% extends "base.html" %}
|
{% raw %}{% extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}Forbidden (403){% endblock %}
|
{% block title %}Forbidden (403){% endblock title %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Forbidden (403)</h1>
|
<h1>Forbidden (403)</h1>
|
||||||
|
<p>
|
||||||
<p>{% if exception %}{{ exception }}{% else %}You're not allowed to access this page.{% endif %}</p>
|
{% if exception %}
|
||||||
|
{{ exception }}
|
||||||
|
{% else %}
|
||||||
|
You're not allowed to access this page.
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
{% raw %}{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Forbidden (403){% endblock title %}
|
||||||
|
{% block content %}
|
||||||
|
<h1>Forbidden (403)</h1>
|
||||||
|
<p>
|
||||||
|
{% if exception %}
|
||||||
|
{{ exception }}
|
||||||
|
{% else %}
|
||||||
|
You're not allowed to access this page.
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
{% endblock content %}
|
||||||
|
{%- endraw %}
|
|
@ -1,10 +1,14 @@
|
||||||
{% raw %}{% extends "base.html" %}
|
{% raw %}{% extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}Page not found{% endblock %}
|
{% block title %}Page not found{% endblock title %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Page not found</h1>
|
<h1>Page not found</h1>
|
||||||
|
<p>
|
||||||
<p>{% if exception %}{{ exception }}{% else %}This is not the page you were looking for.{% endif %}</p>
|
{% if exception %}
|
||||||
|
{{ exception }}
|
||||||
|
{% else %}
|
||||||
|
This is not the page you were looking for.
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
{% raw %}{% extends "base.html" %}
|
{% raw %}{% extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}Server Error{% endblock %}
|
{% block title %}Server Error{% endblock title %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Ooops!!! 500</h1>
|
<h1>Ooops!!! 500</h1>
|
||||||
|
<h3>Looks like something went wrong!</h3>
|
||||||
<h3>Looks like something went wrong!</h3>
|
<p>
|
||||||
|
We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing.
|
||||||
<p>We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing.</p>
|
</p>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Account Inactive" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Account Inactive" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% translate "Account Inactive" %}</h1>
|
<h1>{% translate "Account Inactive" %}</h1>
|
||||||
|
<p>{% translate "This account is inactive." %}</p>
|
||||||
<p>{% translate "This account is inactive." %}</p>
|
{% endblock inner %}
|
||||||
{% endblock %}
|
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
{% raw %}{% extends "base.html" %}
|
{% raw %}{% extends "base.html" %}
|
||||||
{% block title %}{% block head_title %}{% endblock head_title %}{% endblock title %}
|
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% block head_title %}
|
||||||
|
{% endblock head_title %}
|
||||||
|
{% endblock title %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6 offset-md-3">
|
<div class="col-md-6 offset-md-3">
|
||||||
{% block inner %}{% endblock %}
|
{% block inner %}{% endblock inner %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock content %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -4,76 +4,77 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Account" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Account" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% translate "E-mail Addresses" %}</h1>
|
<h1>{% translate "E-mail Addresses" %}</h1>
|
||||||
|
{% if user.emailaddress_set.all %}
|
||||||
{% if user.emailaddress_set.all %}
|
<p>{% translate "The following e-mail addresses are associated with your account:" %}</p>
|
||||||
<p>{% translate 'The following e-mail addresses are associated with your account:' %}</p>
|
<form action="{% url 'account_email' %}" class="email_list" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
<form action="{% url 'account_email' %}" class="email_list" method="post">
|
<fieldset class="blockLabels">
|
||||||
{% csrf_token %}
|
|
||||||
<fieldset class="blockLabels">
|
|
||||||
|
|
||||||
{% for emailaddress in user.emailaddress_set.all %}
|
{% for emailaddress in user.emailaddress_set.all %}
|
||||||
<div class="radio">
|
<div class="radio">
|
||||||
<label for="email_radio_{{forloop.counter}}" class="{% if emailaddress.primary %}primary_email{%endif%}">
|
<label for="email_radio_{{ forloop.counter }}"
|
||||||
|
class="{% if emailaddress.primary %}primary_email{% endif %}">
|
||||||
<input id="email_radio_{{forloop.counter}}" type="radio" name="email" {% if emailaddress.primary or user.emailaddress_set.count == 1 %}checked="checked"{%endif %} value="{{emailaddress.email}}"/>
|
<input id="email_radio_{{ forloop.counter }}"
|
||||||
|
type="radio"
|
||||||
|
name="email"
|
||||||
|
{% if emailaddress.primary or user.emailaddress_set.count == 1 %}checked="checked"{% endif %}
|
||||||
|
value="{{ emailaddress.email }}" />
|
||||||
{{ emailaddress.email }}
|
{{ emailaddress.email }}
|
||||||
{% if emailaddress.verified %}
|
{% if emailaddress.verified %}
|
||||||
<span class="verified">{% translate "Verified" %}</span>
|
<span class="verified">{% translate "Verified" %}</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="unverified">{% translate "Unverified" %}</span>
|
<span class="unverified">{% translate "Unverified" %}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if emailaddress.primary %}<span class="primary">{% translate "Primary" %}</span>{% endif %}
|
{% if emailaddress.primary %}
|
||||||
|
<span class="primary">{% translate "Primary" %}</span>
|
||||||
|
{% endif %}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
<div class="form-group">
|
||||||
<div class="form-group">
|
<button class="secondaryAction btn btn-primary"
|
||||||
<button class="secondaryAction btn btn-primary" type="submit" name="action_primary" >{% translate 'Make Primary' %}</button>
|
type="submit"
|
||||||
<button class="secondaryAction btn btn-primary" type="submit" name="action_send" >{% translate 'Re-send Verification' %}</button>
|
name="action_primary">{% translate "Make Primary" %}</button>
|
||||||
<button class="primaryAction btn btn-primary" type="submit" name="action_remove" >{% translate 'Remove' %}</button>
|
<button class="secondaryAction btn btn-primary"
|
||||||
</div>
|
type="submit"
|
||||||
|
name="action_send">{% translate "Re-send Verification" %}</button>
|
||||||
</fieldset>
|
<button class="primaryAction btn btn-primary"
|
||||||
</form>
|
type="submit"
|
||||||
|
name="action_remove">{% translate "Remove" %}</button>
|
||||||
{% else %}
|
</div>
|
||||||
<p><strong>{% translate 'Warning:'%}</strong> {% translate "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}</p>
|
</fieldset>
|
||||||
|
</form>
|
||||||
{% endif %}
|
{% else %}
|
||||||
|
<p>
|
||||||
|
<strong>{% translate "Warning:" %}</strong> {% translate "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
<h2>{% translate "Add E-mail Address" %}</h2>
|
<h2>{% translate "Add E-mail Address" %}</h2>
|
||||||
|
|
||||||
<form method="post" action="{% url 'account_email' %}" class="add_email">
|
<form method="post" action="{% url 'account_email' %}" class="add_email">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
<button class="btn btn-primary" name="action_add" type="submit">{% translate "Add E-mail" %}</button>
|
<button class="btn btn-primary" name="action_add" type="submit">{% translate "Add E-mail" %}</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% endblock inner %}
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
{% block inline_javascript %}
|
{% block inline_javascript %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.addEventListener('DOMContentLoaded',function() {
|
window.addEventListener('DOMContentLoaded', function() {
|
||||||
const message = "{% translate 'Do you really want to remove the selected e-mail address?' %}";
|
const message = "{% translate 'Do you really want to remove the selected e-mail address?' %}";
|
||||||
const actions = document.getElementsByName('action_remove');
|
const actions = document.getElementsByName('action_remove');
|
||||||
if (actions.length) {
|
if (actions.length) {
|
||||||
actions[0].addEventListener("click",function(e) {
|
actions[0].addEventListener("click", function(e) {
|
||||||
if (!confirm(message)) {
|
if (!confirm(message)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Array.from(document.getElementsByClassName('form-group')).forEach(x => x.classList.remove('row'));
|
Array.from(document.getElementsByClassName('form-group')).forEach(x => x.classList.remove('row'));
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock inline_javascript %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -3,30 +3,26 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load account %}
|
{% load account %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Confirm E-mail Address" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Confirm E-mail Address" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% translate "Confirm E-mail Address" %}</h1>
|
<h1>{% translate "Confirm E-mail Address" %}</h1>
|
||||||
|
{% if confirmation %}
|
||||||
{% if confirmation %}
|
{% user_display confirmation.email_address.user as user_display %}
|
||||||
|
<p>
|
||||||
{% user_display confirmation.email_address.user as user_display %}
|
{% blocktranslate with confirmation.email_address.email as email %}Please confirm that <a href="mailto:{{ email }}">{{ email }}</a> is an e-mail address for user {{ user_display }}.{% endblocktranslate %}
|
||||||
|
</p>
|
||||||
<p>{% blocktranslate with confirmation.email_address.email as email %}Please confirm that <a href="mailto:{{ email }}">{{ email }}</a> is an e-mail address for user {{ user_display }}.{% endblocktranslate %}</p>
|
<form method="post"
|
||||||
|
action="{% url 'account_confirm_email' confirmation.key %}">
|
||||||
<form method="post" action="{% url 'account_confirm_email' confirmation.key %}">
|
{% csrf_token %}
|
||||||
{% csrf_token %}
|
<button class="btn btn-primary" type="submit">{% translate "Confirm" %}</button>
|
||||||
<button class="btn btn-primary" type="submit">{% translate 'Confirm' %}</button>
|
</form>
|
||||||
</form>
|
{% else %}
|
||||||
|
{% url 'account_email' as email_url %}
|
||||||
{% else %}
|
<p>
|
||||||
|
{% blocktranslate %}This e-mail confirmation link expired or is invalid. Please <a href="{{ email_url }}">issue a new e-mail confirmation request</a>.{% endblocktranslate %}
|
||||||
{% url 'account_email' as email_url %}
|
</p>
|
||||||
|
{% endif %}
|
||||||
<p>{% blocktranslate %}This e-mail confirmation link expired or is invalid. Please <a href="{{ email_url }}">issue a new e-mail confirmation request</a>.{% endblocktranslate %}</p>
|
{% endblock inner %}
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -4,15 +4,13 @@
|
||||||
{% load account socialaccount %}
|
{% load account socialaccount %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Sign In" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Sign In" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
|
<h1>{% translate "Sign In" %}</h1>
|
||||||
<h1>{% translate "Sign In" %}</h1>
|
{% get_providers as socialaccount_providers %}
|
||||||
|
{% if socialaccount_providers %}
|
||||||
{% get_providers as socialaccount_providers %}
|
|
||||||
|
|
||||||
{% if socialaccount_providers %}
|
|
||||||
<p>
|
<p>
|
||||||
{% translate "Please sign in with one of your existing third party accounts:" %}
|
{% translate "Please sign in with one of your existing third party accounts:" %}
|
||||||
{% if ACCOUNT_ALLOW_REGISTRATION %}
|
{% if ACCOUNT_ALLOW_REGISTRATION %}
|
||||||
|
@ -22,20 +20,14 @@
|
||||||
{% endblocktranslate %}
|
{% endblocktranslate %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="socialaccount_ballot">
|
<div class="socialaccount_ballot">
|
||||||
|
|
||||||
<ul class="socialaccount_providers">
|
<ul class="socialaccount_providers">
|
||||||
{% include "socialaccount/snippets/provider_list.html" with process="login" %}
|
{% include "socialaccount/snippets/provider_list.html" with process="login" %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="login-or">{% translate "or" %}</div>
|
<div class="login-or">{% translate "or" %}</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% include "socialaccount/snippets/login_extra.html" %}
|
{% include "socialaccount/snippets/login_extra.html" %}
|
||||||
|
{% else %}
|
||||||
{% else %}
|
|
||||||
{% if ACCOUNT_ALLOW_REGISTRATION %}
|
{% if ACCOUNT_ALLOW_REGISTRATION %}
|
||||||
<p>
|
<p>
|
||||||
{% blocktranslate trimmed %}
|
{% blocktranslate trimmed %}
|
||||||
|
@ -44,17 +36,18 @@
|
||||||
{% endblocktranslate %}
|
{% endblocktranslate %}
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<form class="login" method="post" action="{% url 'account_login' %}">
|
||||||
<form class="login" method="POST" action="{% url 'account_login' %}">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
{% if redirect_field_value %}
|
{% if redirect_field_value %}
|
||||||
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
|
<input type="hidden"
|
||||||
|
name="{{ redirect_field_name }}"
|
||||||
|
value="{{ redirect_field_value }}" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a class="button secondaryAction" href="{% url 'account_reset_password' %}">{% translate "Forgot Password?" %}</a>
|
<a class="button secondaryAction"
|
||||||
|
href="{% url 'account_reset_password' %}">{% translate "Forgot Password?" %}</a>
|
||||||
<button class="primaryAction btn btn-primary" type="submit">{% translate "Sign In" %}</button>
|
<button class="primaryAction btn btn-primary" type="submit">{% translate "Sign In" %}</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% endblock inner %}
|
||||||
{% endblock %}
|
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -2,19 +2,20 @@
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Sign Out" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Sign Out" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% translate "Sign Out" %}</h1>
|
<h1>{% translate "Sign Out" %}</h1>
|
||||||
|
<p>{% translate "Are you sure you want to sign out?" %}</p>
|
||||||
<p>{% translate 'Are you sure you want to sign out?' %}</p>
|
<form method="post" action="{% url 'account_logout' %}">
|
||||||
|
|
||||||
<form method="post" action="{% url 'account_logout' %}">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% if redirect_field_value %}
|
{% if redirect_field_value %}
|
||||||
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}"/>
|
<input type="hidden"
|
||||||
|
name="{{ redirect_field_name }}"
|
||||||
|
value="{{ redirect_field_value }}" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button class="btn btn-danger" type="submit">{% translate 'Sign Out' %}</button>
|
<button class="btn btn-danger" type="submit">{% translate "Sign Out" %}</button>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock inner %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -3,15 +3,17 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Change Password" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Change Password" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% translate "Change Password" %}</h1>
|
<h1>{% translate "Change Password" %}</h1>
|
||||||
|
<form method="post"
|
||||||
<form method="POST" action="{% url 'account_change_password' %}" class="password_change">
|
action="{% url 'account_change_password' %}"
|
||||||
|
class="password_change">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
<button class="btn btn-primary" type="submit" name="action">{% translate "Change Password" %}</button>
|
<button class="btn btn-primary" type="submit" name="action">{% translate "Change Password" %}</button>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock inner %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -4,23 +4,26 @@
|
||||||
{% load account %}
|
{% load account %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Password Reset" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Password Reset" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
|
|
||||||
<h1>{% translate "Password Reset" %}</h1>
|
<h1>{% translate "Password Reset" %}</h1>
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
{% include "account/snippets/already_logged_in.html" %}
|
{% include "account/snippets/already_logged_in.html" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<p>
|
||||||
<p>{% translate "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}</p>
|
{% translate "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}
|
||||||
|
</p>
|
||||||
<form method="POST" action="{% url 'account_reset_password' %}" class="password_reset">
|
<form method="post"
|
||||||
|
action="{% url 'account_reset_password' %}"
|
||||||
|
class="password_reset">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
<input class="btn btn-primary" type="submit" value="{% translate 'Reset My Password' %}" />
|
<input class="btn btn-primary"
|
||||||
|
type="submit"
|
||||||
|
value="{% translate 'Reset My Password' %}" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<p>{% blocktranslate %}Please contact us if you have any trouble resetting your password.{% endblocktranslate %}</p>
|
<p>{% blocktranslate %}Please contact us if you have any trouble resetting your password.{% endblocktranslate %}</p>
|
||||||
{% endblock %}
|
{% endblock inner %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -3,15 +3,16 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load account %}
|
{% load account %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Password Reset" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Password Reset" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% translate "Password Reset" %}</h1>
|
<h1>{% translate "Password Reset" %}</h1>
|
||||||
|
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
{% include "account/snippets/already_logged_in.html" %}
|
{% include "account/snippets/already_logged_in.html" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<p>
|
||||||
<p>{% blocktranslate %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}</p>
|
{% blocktranslate %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}
|
||||||
{% endblock %}
|
</p>
|
||||||
|
{% endblock inner %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -2,24 +2,36 @@
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
{% block head_title %}{% translate "Change Password" %}{% endblock %}
|
|
||||||
|
|
||||||
|
{% block head_title %}
|
||||||
|
{% translate "Change Password" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% if token_fail %}{% translate "Bad Token" %}{% else %}{% translate "Change Password" %}{% endif %}</h1>
|
<h1>
|
||||||
|
{% if token_fail %}
|
||||||
|
{% translate "Bad Token" %}
|
||||||
|
{% else %}
|
||||||
|
{% translate "Change Password" %}
|
||||||
|
{% endif %}
|
||||||
|
</h1>
|
||||||
{% if token_fail %}
|
{% if token_fail %}
|
||||||
{% url 'account_reset_password' as passwd_reset_url %}
|
{% url 'account_reset_password' as passwd_reset_url %}
|
||||||
<p>{% blocktranslate %}The password reset link was invalid, possibly because it has already been used. Please request a <a href="{{ passwd_reset_url }}">new password reset</a>.{% endblocktranslate %}</p>
|
<p>
|
||||||
|
{% blocktranslate %}The password reset link was invalid, possibly because it has already been used. Please request a <a href="{{ passwd_reset_url }}">new password reset</a>.{% endblocktranslate %}
|
||||||
|
</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if form %}
|
{% if form %}
|
||||||
<form method="POST" action=".">
|
<form method="post" action=".">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
<input class="btn btn-primary" type="submit" name="action" value="{% translate 'change password' %}"/>
|
<input class="btn btn-primary"
|
||||||
|
type="submit"
|
||||||
|
name="action"
|
||||||
|
value="{% translate 'change password' %}" />
|
||||||
</form>
|
</form>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>{% translate 'Your password is now changed.' %}</p>
|
<p>{% translate "Your password is now changed." %}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock inner %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
{% raw %}{% extends "account/base.html" %}
|
{% raw %}{% extends "account/base.html" %}
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block head_title %}{% translate "Change Password" %}{% endblock %}
|
|
||||||
|
|
||||||
|
{% block head_title %}
|
||||||
|
{% translate "Change Password" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% translate "Change Password" %}</h1>
|
<h1>{% translate "Change Password" %}</h1>
|
||||||
<p>{% translate 'Your password is now changed.' %}</p>
|
<p>{% translate "Your password is now changed." %}</p>
|
||||||
{% endblock %}
|
{% endblock inner %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -3,15 +3,20 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Set Password" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Set Password" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% translate "Set Password" %}</h1>
|
<h1>{% translate "Set Password" %}</h1>
|
||||||
|
<form method="post"
|
||||||
<form method="POST" action="{% url 'account_set_password' %}" class="password_set">
|
action="{% url 'account_set_password' %}"
|
||||||
|
class="password_set">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
<input class="btn btn-primary" type="submit" name="action" value="{% translate 'Set Password' %}"/>
|
<input class="btn btn-primary"
|
||||||
|
type="submit"
|
||||||
|
name="action"
|
||||||
|
value="{% translate 'Set Password' %}" />
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock inner %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -3,21 +3,26 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Signup" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Signup" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% translate "Sign Up" %}</h1>
|
<h1>{% translate "Sign Up" %}</h1>
|
||||||
|
<p>
|
||||||
<p>{% blocktranslate %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktranslate %}</p>
|
{% blocktranslate %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktranslate %}
|
||||||
|
</p>
|
||||||
<form class="signup" id="signup_form" method="post" action="{% url 'account_signup' %}">
|
<form class="signup"
|
||||||
|
id="signup_form"
|
||||||
|
method="post"
|
||||||
|
action="{% url 'account_signup' %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
{% if redirect_field_value %}
|
{% if redirect_field_value %}
|
||||||
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
|
<input type="hidden"
|
||||||
|
name="{{ redirect_field_name }}"
|
||||||
|
value="{{ redirect_field_value }}" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button class="btn btn-primary" type="submit">{% translate "Sign Up" %} »</button>
|
<button class="btn btn-primary" type="submit">{% translate "Sign Up" %} »</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% endblock inner %}
|
||||||
{% endblock %}
|
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Sign Up Closed" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Sign Up Closed" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% translate "Sign Up Closed" %}</h1>
|
<h1>{% translate "Sign Up Closed" %}</h1>
|
||||||
|
<p>{% translate "We are sorry, but the sign up is currently closed." %}</p>
|
||||||
<p>{% translate "We are sorry, but the sign up is currently closed." %}</p>
|
{% endblock inner %}
|
||||||
{% endblock %}
|
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Verify Your E-mail Address" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Verify Your E-mail Address" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% translate "Verify Your E-mail Address" %}</h1>
|
<h1>{% translate "Verify Your E-mail Address" %}</h1>
|
||||||
|
<p>
|
||||||
<p>{% blocktranslate %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}</p>
|
{% blocktranslate %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}
|
||||||
|
</p>
|
||||||
{% endblock %}
|
{% endblock inner %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -2,21 +2,24 @@
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block head_title %}{% translate "Verify Your E-mail Address" %}{% endblock %}
|
{% block head_title %}
|
||||||
|
{% translate "Verify Your E-mail Address" %}
|
||||||
|
{% endblock head_title %}
|
||||||
{% block inner %}
|
{% block inner %}
|
||||||
<h1>{% translate "Verify Your E-mail Address" %}</h1>
|
<h1>{% translate "Verify Your E-mail Address" %}</h1>
|
||||||
|
{% url 'account_email' as email_url %}
|
||||||
{% url 'account_email' as email_url %}
|
<p>
|
||||||
|
{% blocktranslate %}This part of the site requires us to verify that
|
||||||
<p>{% blocktranslate %}This part of the site requires us to verify that
|
|
||||||
you are who you claim to be. For this purpose, we require that you
|
you are who you claim to be. For this purpose, we require that you
|
||||||
verify ownership of your e-mail address. {% endblocktranslate %}</p>
|
verify ownership of your e-mail address. {% endblocktranslate %}
|
||||||
|
</p>
|
||||||
<p>{% blocktranslate %}We have sent an e-mail to you for
|
<p>
|
||||||
|
{% blocktranslate %}We have sent an e-mail to you for
|
||||||
verification. Please click on the link inside this e-mail. Please
|
verification. Please click on the link inside this e-mail. Please
|
||||||
contact us if you do not receive it within a few minutes.{% endblocktranslate %}</p>
|
contact us if you do not receive it within a few minutes.{% endblocktranslate %}
|
||||||
|
</p>
|
||||||
<p>{% blocktranslate %}<strong>Note:</strong> you can still <a href="{{ email_url }}">change your e-mail address</a>.{% endblocktranslate %}</p>
|
<p>
|
||||||
{% endblock %}
|
{% blocktranslate %}<strong>Note:</strong> you can still <a href="{{ email_url }}">change your e-mail address</a>.{% endblocktranslate %}
|
||||||
|
</p>
|
||||||
|
{% endblock inner %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -1,87 +1,130 @@
|
||||||
{% raw %}{% load static i18n {% endraw %}
|
{% raw %}
|
||||||
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}compress
|
{% load static i18n {% endraw %}
|
||||||
{%- endif %}{% raw %}%}{% endraw %}
|
|
||||||
{%- if cookiecutter.frontend_pipeline == 'Webpack' %}{% raw %}{% load render_bundle from webpack_loader %}{% endraw %}
|
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}compress{%- endif %}{% raw %}%}{% endraw %}
|
||||||
|
{%- if cookiecutter.frontend_pipeline == 'Webpack' %}{% raw %}
|
||||||
|
{% load render_bundle from webpack_loader %}
|
||||||
|
|
||||||
|
{% endraw %}
|
||||||
{%- endif %}{% raw %}<!DOCTYPE html>
|
{%- endif %}{% raw %}<!DOCTYPE html>
|
||||||
{% get_current_language as LANGUAGE_CODE %}
|
{% get_current_language as LANGUAGE_CODE %}
|
||||||
<html lang="{{ LANGUAGE_CODE }}">
|
<html lang="{{ LANGUAGE_CODE }}">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
||||||
<title>{% block title %}{% endraw %}{{ cookiecutter.project_name }}{% raw %}{% endblock title %}</title>
|
<title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
{% block title %}
|
||||||
<meta name="description" content="{% endraw %}{{ cookiecutter.description }}{% raw %}">
|
{% endraw %}{{ cookiecutter.project_name }}{% raw %}
|
||||||
<meta name="author" content="{% endraw %}{{ cookiecutter.author_name }}{% raw %}">
|
{% endblock title %}
|
||||||
|
</title>
|
||||||
<link rel="icon" href="{% static 'images/favicons/favicon.ico' %}">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta name="description"
|
||||||
|
content="{% endraw %}{{ cookiecutter.description }}{% raw %}" />
|
||||||
|
<meta name="author"
|
||||||
|
content="{% endraw %}{{ cookiecutter.author_name }}{% raw %}" />
|
||||||
|
<link rel="icon" href="{% static 'images/favicons/favicon.ico' %}" />
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
{%- if cookiecutter.frontend_pipeline in ['None', 'Django Compressor'] %}
|
{%- if cookiecutter.frontend_pipeline in ['None', 'Django Compressor'] %}
|
||||||
{%- raw %}
|
{%- raw %}
|
||||||
<!-- Latest compiled and minified Bootstrap CSS -->
|
<!-- Latest compiled and minified Bootstrap CSS -->
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/css/bootstrap.min.css" integrity="sha512-SbiR/eusphKoMVVXysTKG/7VseWii+Y3FdHrt0EpKgpToZeemhqHeZeLWLhJutz/2ut2Vw1uQEj2MbRF+TVBUA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
<link rel="stylesheet"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/css/bootstrap.min.css"
|
||||||
|
integrity="sha512-SbiR/eusphKoMVVXysTKG/7VseWii+Y3FdHrt0EpKgpToZeemhqHeZeLWLhJutz/2ut2Vw1uQEj2MbRF+TVBUA=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer" />
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- raw %}
|
{%- raw %}
|
||||||
<!-- Your stuff: Third-party CSS libraries go here -->
|
<!-- Your stuff: Third-party CSS libraries go here -->
|
||||||
|
<!-- This file stores project-specific CSS -->
|
||||||
<!-- This file stores project-specific CSS -->
|
{%- endraw %}
|
||||||
{%- endraw %}{% if cookiecutter.frontend_pipeline == 'None' %}{% raw %}
|
{% if cookiecutter.frontend_pipeline == 'None' %}
|
||||||
<link href="{% static 'css/project.css' %}" rel="stylesheet">
|
{% raw %}
|
||||||
{%- endraw %}{% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}{% raw %}
|
<link href="{% static 'css/project.css' %}" rel="stylesheet" />
|
||||||
{% compress css %}
|
{%- endraw %}
|
||||||
<link href="{% static 'css/project.css' %}" rel="stylesheet">
|
{% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}
|
||||||
{% endcompress %}
|
{% raw %}
|
||||||
{%- endraw %}{% elif cookiecutter.frontend_pipeline == 'Gulp' %}{% raw %}
|
{% compress css %}
|
||||||
<link href="{% static 'css/project.min.css' %}" rel="stylesheet">
|
<link href="{% static 'css/project.css' %}" rel="stylesheet" />
|
||||||
{%- endraw %}{% elif cookiecutter.frontend_pipeline == "Webpack" %}{% raw %}
|
{% endcompress %}
|
||||||
{% render_bundle 'project' 'css' %}
|
{%- endraw %}
|
||||||
{%- endraw %}{% endif %}{% raw %}
|
{% elif cookiecutter.frontend_pipeline == 'Gulp' %}
|
||||||
{% endblock %}
|
{% raw %}
|
||||||
<!-- Le javascript
|
<link href="{% static 'css/project.min.css' %}" rel="stylesheet" />
|
||||||
|
{%- endraw %}
|
||||||
|
{% elif cookiecutter.frontend_pipeline == "Webpack" %}
|
||||||
|
{% raw %}
|
||||||
|
{% render_bundle 'project' 'css' %}
|
||||||
|
{%- endraw %}
|
||||||
|
{% endif %}
|
||||||
|
{% raw %}
|
||||||
|
{% endblock css %}
|
||||||
|
<!-- Le javascript
|
||||||
================================================== -->
|
================================================== -->
|
||||||
{# Placed at the top of the document so pages load faster with defer #}
|
{# Placed at the top of the document so pages load faster with defer #}
|
||||||
{% block javascript %}
|
{% block javascript %}
|
||||||
{%- endraw %}{% if cookiecutter.frontend_pipeline == 'Gulp' %}{% raw %}
|
{%- endraw %}
|
||||||
|
{% if cookiecutter.frontend_pipeline == 'Gulp' %}
|
||||||
|
{% raw %}
|
||||||
<!-- Vendor dependencies bundled as one file -->
|
<!-- Vendor dependencies bundled as one file -->
|
||||||
<script defer src="{% static 'js/vendors.min.js' %}"></script>
|
<script defer src="{% static 'js/vendors.min.js' %}"></script>
|
||||||
{%- endraw %}{% elif cookiecutter.frontend_pipeline == "Webpack" %}{% raw %}
|
{%- endraw %}
|
||||||
<!-- Vendor dependencies bundled as one file -->
|
{% elif cookiecutter.frontend_pipeline == "Webpack" %}
|
||||||
{% render_bundle 'vendors' 'js' attrs='defer' %}
|
{% raw %}
|
||||||
{%- endraw %}{% else %}{% raw %}
|
<!-- Vendor dependencies bundled as one file -->
|
||||||
<!-- Bootstrap JS -->
|
{% render_bundle 'vendors' 'js' attrs='defer' %}
|
||||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.min.js" integrity="sha512-1/RvZTcCDEUjY/CypiMz+iqqtaoQfAITmNSJY17Myp4Ms5mdxPS5UV7iOfdZoxcGhzFbOm6sntTKJppjvuhg4g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
{%- endraw %}
|
||||||
<!-- Your stuff: Third-party javascript libraries go here -->
|
{% else %}
|
||||||
{%- endraw %}{% endif %}{% raw %}
|
{% raw %}
|
||||||
|
<!-- Bootstrap JS -->
|
||||||
<!-- place project specific Javascript in this file -->
|
<script defer
|
||||||
{%- endraw %}{% if cookiecutter.frontend_pipeline == 'None' %}{% raw %}
|
src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.min.js"
|
||||||
|
integrity="sha512-1/RvZTcCDEUjY/CypiMz+iqqtaoQfAITmNSJY17Myp4Ms5mdxPS5UV7iOfdZoxcGhzFbOm6sntTKJppjvuhg4g=="
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"></script>
|
||||||
|
<!-- Your stuff: Third-party javascript libraries go here -->
|
||||||
|
{%- endraw %}
|
||||||
|
{% endif %}
|
||||||
|
{% raw %}
|
||||||
|
<!-- place project specific Javascript in this file -->
|
||||||
|
{%- endraw %}
|
||||||
|
{% if cookiecutter.frontend_pipeline == 'None' %}
|
||||||
|
{% raw %}
|
||||||
<script defer src="{% static 'js/project.js' %}"></script>
|
<script defer src="{% static 'js/project.js' %}"></script>
|
||||||
{%- endraw %}{% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}{% raw %}
|
{%- endraw %}
|
||||||
{% compress js %}
|
{% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}
|
||||||
|
{% raw %}
|
||||||
|
{% compress js %}
|
||||||
<script defer src="{% static 'js/project.js' %}"></script>
|
<script defer src="{% static 'js/project.js' %}"></script>
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
{%- endraw %}{% elif cookiecutter.frontend_pipeline == 'Gulp' %}{% raw %}
|
{%- endraw %}
|
||||||
<script defer src="{% static 'js/project.min.js' %}"></script>
|
{% elif cookiecutter.frontend_pipeline == 'Gulp' %}
|
||||||
{%- endraw %}{% elif cookiecutter.frontend_pipeline == "Webpack" %}{% raw %}
|
{% raw %}
|
||||||
{% render_bundle 'project' 'js' attrs='defer' %}
|
<script defer src="{% static 'js/project.min.js' %}"></script>
|
||||||
{%- endraw %}{% endif %}{% raw %}
|
{%- endraw %}
|
||||||
|
{% elif cookiecutter.frontend_pipeline == "Webpack" %}
|
||||||
{% endblock javascript %}
|
{% raw %}
|
||||||
|
{% render_bundle 'project' 'js' attrs='defer' %}
|
||||||
</head>
|
{%- endraw %}
|
||||||
|
{% endif %}
|
||||||
<body>
|
{% raw %}
|
||||||
|
{% endblock javascript %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
<div class="mb-1">
|
<div class="mb-1">
|
||||||
<nav class="navbar navbar-expand-md navbar-light bg-light">
|
<nav class="navbar navbar-expand-md navbar-light bg-light">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<button class="navbar-toggler navbar-toggler-right" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler navbar-toggler-right"
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="collapse"
|
||||||
|
data-bs-target="#navbarSupportedContent"
|
||||||
|
aria-controls="navbarSupportedContent"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand" href="{% url 'home' %}">{% endraw %}{{ cookiecutter.project_name }}{% raw %}</a>
|
<a class="navbar-brand" href="{% url 'home' %}">{% endraw %}{{ cookiecutter.project_name }}{% raw %}</a>
|
||||||
|
|
||||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
<ul class="navbar-nav mr-auto">
|
<ul class="navbar-nav mr-auto">
|
||||||
<li class="nav-item active">
|
<li class="nav-item active">
|
||||||
|
@ -92,7 +135,8 @@
|
||||||
</li>
|
</li>
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{% url 'users:detail' request.user.pk %}{% endraw %}{% else %}{% raw %}{% url 'users:detail' request.user.username %}{% endraw %}{% endif %}{% raw %}">{% translate "My Profile" %}</a>
|
<a class="nav-link"
|
||||||
|
href="{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{% url 'users:detail' request.user.pk %}{% endraw %}{% else %}{% raw %}{% url 'users:detail' request.user.username %}{% endraw %}{% endif %}{% raw %}">{% translate "My Profile" %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
{# URL provided by django-allauth/account/urls.py #}
|
{# URL provided by django-allauth/account/urls.py #}
|
||||||
|
@ -114,37 +158,37 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
{% for message in messages %}
|
{% for message in messages %}
|
||||||
<div class="alert alert-dismissible {% if message.tags %}alert-{{ message.tags }}{% endif %}">
|
<div class="alert alert-dismissible {% if message.tags %}alert-{{ message.tags }}{% endif %}">
|
||||||
{{ message }}
|
{{ message }}
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
<button type="button"
|
||||||
|
class="btn-close"
|
||||||
|
data-bs-dismiss="alert"
|
||||||
|
aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<p>Use this document as a way to quick start any new project.</p>
|
<p>Use this document as a way to quick start any new project.</p>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
</div>
|
||||||
</div> <!-- /container -->
|
<!-- /container -->
|
||||||
|
{% block modal %}
|
||||||
{% block modal %}{% endblock modal %}
|
{% endblock modal %}
|
||||||
|
|
||||||
{% block inline_javascript %}
|
{% block inline_javascript %}
|
||||||
{% comment %}
|
{% comment %}
|
||||||
Script tags with only code, no src (defer by default). To run
|
Script tags with only code, no src (defer by default). To run
|
||||||
with a "defer" so that you run inline code:
|
with a "defer" so that you run inline code:
|
||||||
<script>
|
<script>
|
||||||
window.addEventListener('DOMContentLoaded', () => {/* Run whatever you want */});
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
|
/* Run whatever you want */
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endcomment %}
|
{% endcomment %}
|
||||||
{% endblock inline_javascript %}
|
{% endblock inline_javascript %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
{% raw %}{% extends "base.html" %}{% endraw %}
|
{% raw %}{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% endraw %}
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
{% raw %}{% extends "base.html" %}{% endraw %}
|
{% raw %}{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% endraw %}
|
||||||
|
|
|
@ -1,35 +1,51 @@
|
||||||
{% raw %}{% extends "base.html" %}
|
{% raw %}{% extends "base.html" %}
|
||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
{% block title %}User: {% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{{ object.name }}{% endraw %}{% else %}{% raw %}{{ object.username }}{% endraw %}{% endif %}{% raw %}{% endblock %}
|
{% block title %}
|
||||||
|
User: {% endraw %}
|
||||||
|
{% if cookiecutter.username_type == "email" %}
|
||||||
|
{% raw %}{{ object.name }}{% endraw %}
|
||||||
|
{% else %}
|
||||||
|
{% raw %}{{ object.username }}{% endraw %}
|
||||||
|
{% endif %}
|
||||||
|
{% raw %}
|
||||||
|
{% endblock title %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
|
<h2>
|
||||||
<h2>{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{{ object.name }}{% endraw %}{% else %}{% raw %}{{ object.username }}{% endraw %}{% endif %}{% raw %}</h2>
|
{% endraw %}
|
||||||
|
{% if cookiecutter.username_type == "email" %}
|
||||||
|
{% raw %}{{ object.name }}{% endraw %}
|
||||||
|
{% else %}
|
||||||
|
{% raw %}{{ object.username }}{% endraw %}
|
||||||
|
{% endif %}
|
||||||
|
</h2>
|
||||||
|
{%- if cookiecutter.username_type == "username" %}
|
||||||
|
{%- raw %}
|
||||||
{% if object.name %}
|
{% if object.name %}
|
||||||
<p>{{ object.name }}</p>
|
<p>{{ object.name }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{%- endraw %}
|
||||||
|
{%- endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{%- raw %}
|
||||||
{% if object == request.user %}
|
{% if object == request.user %}
|
||||||
<!-- Action buttons -->
|
<!-- Action buttons -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<a class="btn btn-primary" href="{% url 'users:update' %}" role="button">My Info</a>
|
<a class="btn btn-primary" href="{% url 'users:update' %}" role="button">My Info</a>
|
||||||
<a class="btn btn-primary" href="{% url 'account_email' %}" role="button">E-Mail</a>
|
<a class="btn btn-primary"
|
||||||
|
href="{% url 'account_email' %}"
|
||||||
|
role="button">E-Mail</a>
|
||||||
<!-- Your Stuff: Custom user template urls -->
|
<!-- Your Stuff: Custom user template urls -->
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
<!-- End Action buttons -->
|
||||||
<!-- End Action buttons -->
|
{% endif %}
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -1,11 +1,29 @@
|
||||||
{% raw %}{% extends "base.html" %}
|
{% raw %}{% extends "base.html" %}
|
||||||
|
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
{% block title %}{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{{ user.name }}{% endraw %}{% else %}{% raw %}{{ user.username }}{% endraw %}{% endif %}{% raw %}{% endblock %}
|
{% block title %}
|
||||||
|
{% endraw %}
|
||||||
|
{% if cookiecutter.username_type == "email" %}
|
||||||
|
{% raw %}{{ user.name }}{% endraw %}
|
||||||
|
{% else %}
|
||||||
|
{% raw %}{{ user.username }}{% endraw %}
|
||||||
|
{% endif %}
|
||||||
|
{% raw %}
|
||||||
|
{% endblock title %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{{ user.name }}{% endraw %}{% else %}{% raw %}{{ user.username }}{% endraw %}{% endif %}{% raw %}</h1>
|
<h1>
|
||||||
<form class="form-horizontal" method="post" action="{% url 'users:update' %}">
|
{% endraw %}
|
||||||
|
{% if cookiecutter.username_type == "email" %}
|
||||||
|
{% raw %}{{ user.name }}{% endraw %}
|
||||||
|
{% else %}
|
||||||
|
{% raw %}{{ user.username }}{% endraw %}
|
||||||
|
{% endif %}
|
||||||
|
{% raw %}
|
||||||
|
</h1>
|
||||||
|
<form class="form-horizontal"
|
||||||
|
method="post"
|
||||||
|
action="{% url 'users:update' %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
|
@ -13,6 +31,6 @@
|
||||||
<button type="submit" class="btn btn-primary">Update</button>
|
<button type="submit" class="btn btn-primary">Update</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock content %}
|
||||||
{%- endraw %}
|
{%- endraw %}
|
||||||
|
|
|
@ -1,16 +1,37 @@
|
||||||
from typing import Any
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import typing
|
||||||
|
|
||||||
from allauth.account.adapter import DefaultAccountAdapter
|
from allauth.account.adapter import DefaultAccountAdapter
|
||||||
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
|
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
|
|
||||||
|
if typing.TYPE_CHECKING:
|
||||||
|
from allauth.socialaccount.models import SocialLogin
|
||||||
|
from {{cookiecutter.project_slug}}.users.models import User
|
||||||
|
|
||||||
|
|
||||||
class AccountAdapter(DefaultAccountAdapter):
|
class AccountAdapter(DefaultAccountAdapter):
|
||||||
def is_open_for_signup(self, request: HttpRequest):
|
def is_open_for_signup(self, request: HttpRequest) -> bool:
|
||||||
return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True)
|
return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True)
|
||||||
|
|
||||||
|
|
||||||
class SocialAccountAdapter(DefaultSocialAccountAdapter):
|
class SocialAccountAdapter(DefaultSocialAccountAdapter):
|
||||||
def is_open_for_signup(self, request: HttpRequest, sociallogin: Any):
|
def is_open_for_signup(self, request: HttpRequest, sociallogin: SocialLogin) -> bool:
|
||||||
return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True)
|
return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True)
|
||||||
|
|
||||||
|
def populate_user(self, request: HttpRequest, sociallogin: SocialLogin, data: dict[str, typing.Any]) -> User:
|
||||||
|
"""
|
||||||
|
Populates user information from social provider info.
|
||||||
|
|
||||||
|
See: https://django-allauth.readthedocs.io/en/latest/advanced.html?#creating-and-populating-user-instances
|
||||||
|
"""
|
||||||
|
user = sociallogin.user
|
||||||
|
if name := data.get("name"):
|
||||||
|
user.name = name
|
||||||
|
elif first_name := data.get("first_name"):
|
||||||
|
user.name = first_name
|
||||||
|
if last_name := data.get("last_name"):
|
||||||
|
user.name += f" {last_name}"
|
||||||
|
return super().populate_user(request, sociallogin, data)
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth import admin as auth_admin
|
from django.contrib.auth import admin as auth_admin
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model, decorators
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from {{ cookiecutter.project_slug }}.users.forms import UserAdminChangeForm, UserAdminCreationForm
|
from {{ cookiecutter.project_slug }}.users.forms import UserAdminChangeForm, UserAdminCreationForm
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
if settings.DJANGO_ADMIN_FORCE_ALLAUTH:
|
||||||
|
# Force the `admin` sign in process to go through the `django-allauth` workflow:
|
||||||
|
# https://django-allauth.readthedocs.io/en/stable/advanced.html#admin
|
||||||
|
admin.site.login = decorators.login_required(admin.site.login) # type: ignore[method-assign]
|
||||||
|
|
||||||
|
|
||||||
@admin.register(User)
|
@admin.register(User)
|
||||||
class UserAdmin(auth_admin.UserAdmin):
|
class UserAdmin(auth_admin.UserAdmin):
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from {{ cookiecutter.project_slug }}.users.models import User as UserType
|
||||||
|
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class UserSerializer(serializers.ModelSerializer):
|
class UserSerializer(serializers.ModelSerializer[UserType]):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
{%- if cookiecutter.username_type == "email" %}
|
{%- if cookiecutter.username_type == "email" %}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user