mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-09-20 19:02:37 +03:00
Update CC 2024-03-22
This commit is contained in:
parent
111c983a9b
commit
3280e19e41
32
.github/contributors.json
vendored
32
.github/contributors.json
vendored
|
@ -1115,7 +1115,7 @@
|
|||
"twitter_username": "Qoyyuum"
|
||||
},
|
||||
{
|
||||
"name": "mfosterw",
|
||||
"name": "Matthew Foster Walsh",
|
||||
"github_login": "mfosterw",
|
||||
"twitter_username": ""
|
||||
},
|
||||
|
@ -1508,5 +1508,35 @@
|
|||
"name": "Nix Siow",
|
||||
"github_login": "nixsiow",
|
||||
"twitter_username": "nixsiow"
|
||||
},
|
||||
{
|
||||
"name": "Jens Kaeske",
|
||||
"github_login": "jkaeske",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "henningbra",
|
||||
"github_login": "henningbra",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "Paul Wulff",
|
||||
"github_login": "mtmpaulwulff",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "Mounir",
|
||||
"github_login": "mounirmesselmeni",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "JAEGYUN JUNG",
|
||||
"github_login": "TGoddessana",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "Simeon Emanuilov",
|
||||
"github_login": "s-emanuilov",
|
||||
"twitter_username": "s_emanuilov"
|
||||
}
|
||||
]
|
16
.github/dependabot.yml
vendored
16
.github/dependabot.yml
vendored
|
@ -3,6 +3,22 @@
|
|||
|
||||
version: 2
|
||||
updates:
|
||||
# Update Python deps for the template (not the generated project)
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
labels:
|
||||
- "project infrastructure"
|
||||
|
||||
# Update Python deps for the documentation
|
||||
- package-ecosystem: "pip"
|
||||
directory: "docs/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
labels:
|
||||
- "project infrastructure"
|
||||
|
||||
# Update GitHub actions in workflows
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
|
|
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
|
@ -25,7 +25,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version: "3.12"
|
||||
cache: pip
|
||||
- name: Install dependencies
|
||||
run: pip install -r requirements.txt
|
||||
|
@ -56,7 +56,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version: "3.12"
|
||||
cache: pip
|
||||
- name: Install dependencies
|
||||
run: pip install -r requirements.txt
|
||||
|
@ -100,7 +100,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version: "3.12"
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
requirements.txt
|
||||
|
|
2
.github/workflows/django-issue-checker.yml
vendored
2
.github/workflows/django-issue-checker.yml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version: "3.12"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
|
|
6
.github/workflows/issue-manager.yml
vendored
6
.github/workflows/issue-manager.yml
vendored
|
@ -23,7 +23,7 @@ jobs:
|
|||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: tiangolo/issue-manager@0.4.1
|
||||
- uses: tiangolo/issue-manager@0.5.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
config: >
|
||||
|
@ -39,5 +39,9 @@ jobs:
|
|||
"waiting": {
|
||||
"delay": 864000,
|
||||
"message": "Automatically closing after waiting for additional info. To re-open, please provide the additional information requested."
|
||||
},
|
||||
"wontfix": {
|
||||
"delay": 864000,
|
||||
"message": "As discussed, we won't be implementing this. Automatically closing."
|
||||
}
|
||||
}
|
||||
|
|
4
.github/workflows/pre-commit-autoupdate.yml
vendored
4
.github/workflows/pre-commit-autoupdate.yml
vendored
|
@ -24,7 +24,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install pre-commit
|
||||
run: pip install pre-commit
|
||||
|
@ -37,7 +37,7 @@ jobs:
|
|||
run: pre-commit autoupdate
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: update/pre-commit-autoupdate
|
||||
|
|
2
.github/workflows/update-changelog.yml
vendored
2
.github/workflows/update-changelog.yml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
|||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version: "3.12"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
|
|
2
.github/workflows/update-contributors.yml
vendored
2
.github/workflows/update-contributors.yml
vendored
|
@ -22,7 +22,7 @@ jobs:
|
|||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
python-version: "3.12"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
|
|
|
@ -2,7 +2,7 @@ exclude: "{{cookiecutter.project_slug}}|.github/contributors.json|CHANGELOG.md|C
|
|||
default_stages: [commit]
|
||||
|
||||
default_language_version:
|
||||
python: python3.11
|
||||
python: python3.12
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
|
@ -26,14 +26,14 @@ repos:
|
|||
args: ["--tab-width", "2"]
|
||||
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.15.0
|
||||
rev: v3.15.1
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py311-plus]
|
||||
args: [--py312-plus]
|
||||
exclude: hooks/
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.12.1
|
||||
rev: 24.3.0
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@ pin: True
|
|||
label_prs: update
|
||||
|
||||
requirements:
|
||||
- "requirements.txt"
|
||||
- "docs/requirements.txt"
|
||||
- "{{cookiecutter.project_slug}}/requirements/base.txt"
|
||||
- "{{cookiecutter.project_slug}}/requirements/local.txt"
|
||||
- "{{cookiecutter.project_slug}}/requirements/production.txt"
|
||||
|
|
|
@ -8,7 +8,7 @@ version: 2
|
|||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
python: "3.12"
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
|
|
365
CHANGELOG.md
365
CHANGELOG.md
|
@ -3,6 +3,371 @@ All enhancements and patches to Cookiecutter Django will be documented in this f
|
|||
|
||||
<!-- GENERATOR_PLACEHOLDER -->
|
||||
|
||||
## 2024.03.21
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Add PostgreSQL 16, remove Postgres 10 and 11 ([#4935](https://github.com/cookiecutter/cookiecutter-django/pull/4935))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update uvicorn to 0.29.0 ([#4933](https://github.com/cookiecutter/cookiecutter-django/pull/4933))
|
||||
|
||||
- Update sentry-sdk to 1.43.0 ([#4934](https://github.com/cookiecutter/cookiecutter-django/pull/4934))
|
||||
|
||||
## 2024.03.19
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Add documentation to upgrade Postgres in Docker environment. Fix: #461 ([#4898](https://github.com/cookiecutter/cookiecutter-django/pull/4898))
|
||||
|
||||
- Upgrade Python to version 3.12 ([#4930](https://github.com/cookiecutter/cookiecutter-django/pull/4930))
|
||||
|
||||
## 2024.03.18
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Split the docs from local.yml and build the service in CI ([#4909](https://github.com/cookiecutter/cookiecutter-django/pull/4909))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update django-anymail to 10.3 ([#4919](https://github.com/cookiecutter/cookiecutter-django/pull/4919))
|
||||
|
||||
- Update sentry-sdk to 1.42.0 ([#4921](https://github.com/cookiecutter/cookiecutter-django/pull/4921))
|
||||
|
||||
- Update coverage to 7.4.4 ([#4926](https://github.com/cookiecutter/cookiecutter-django/pull/4926))
|
||||
|
||||
- Update ruff to 0.3.3 ([#4927](https://github.com/cookiecutter/cookiecutter-django/pull/4927))
|
||||
|
||||
- Auto-update pre-commit hooks ([#4928](https://github.com/cookiecutter/cookiecutter-django/pull/4928))
|
||||
|
||||
## 2024.03.17
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update djangorestframework to 3.15.0 ([#4929](https://github.com/cookiecutter/cookiecutter-django/pull/4929))
|
||||
|
||||
## 2024.03.10
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Auto-update pre-commit hooks ([#4912](https://github.com/cookiecutter/cookiecutter-django/pull/4912))
|
||||
|
||||
- Update ruff to 0.3.2 ([#4911](https://github.com/cookiecutter/cookiecutter-django/pull/4911))
|
||||
|
||||
- Update uvicorn to 0.28.0 ([#4913](https://github.com/cookiecutter/cookiecutter-django/pull/4913))
|
||||
|
||||
- Update redis to 5.0.3 ([#4916](https://github.com/cookiecutter/cookiecutter-django/pull/4916))
|
||||
|
||||
- Update pytest to 8.1.1 ([#4914](https://github.com/cookiecutter/cookiecutter-django/pull/4914))
|
||||
|
||||
## 2024.03.07
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Auto-update pre-commit hooks ([#4907](https://github.com/cookiecutter/cookiecutter-django/pull/4907))
|
||||
|
||||
- Update sentry-sdk to 1.41.0 ([#4908](https://github.com/cookiecutter/cookiecutter-django/pull/4908))
|
||||
|
||||
## 2024.03.06
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix fully qualified docker images ([#4905](https://github.com/cookiecutter/cookiecutter-django/pull/4905))
|
||||
|
||||
## 2024.03.04
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update pytest to 8.1.0 ([#4900](https://github.com/cookiecutter/cookiecutter-django/pull/4900))
|
||||
|
||||
- Update django to 4.2.11 ([#4901](https://github.com/cookiecutter/cookiecutter-django/pull/4901))
|
||||
|
||||
## 2024.03.03
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update django-celery-beat to 2.6.0 ([#4899](https://github.com/cookiecutter/cookiecutter-django/pull/4899))
|
||||
|
||||
## 2024.03.01
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Add a maintainer guide to the docs ([#4884](https://github.com/cookiecutter/cookiecutter-django/pull/4884))
|
||||
|
||||
### Updated
|
||||
|
||||
- Auto-update pre-commit hooks ([#4897](https://github.com/cookiecutter/cookiecutter-django/pull/4897))
|
||||
|
||||
- Update ruff to 0.3.0 ([#4896](https://github.com/cookiecutter/cookiecutter-django/pull/4896))
|
||||
|
||||
## 2024.02.28
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix invalid HTML in django-allauth field element template ([#4894](https://github.com/cookiecutter/cookiecutter-django/pull/4894))
|
||||
|
||||
- Fix permissions for media files when served by nginx ([#4889](https://github.com/cookiecutter/cookiecutter-django/pull/4889))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Fix broken "Two scoops of django" link in FAQ ([#4892](https://github.com/cookiecutter/cookiecutter-django/pull/4892))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update redis to 5.0.2 ([#4895](https://github.com/cookiecutter/cookiecutter-django/pull/4895))
|
||||
|
||||
- Update sentry-sdk to 1.40.6 ([#4893](https://github.com/cookiecutter/cookiecutter-django/pull/4893))
|
||||
|
||||
## 2024.02.26
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Allauth elements & MFA ([#4843](https://github.com/cookiecutter/cookiecutter-django/pull/4843))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update pytest to 8.0.2 ([#4890](https://github.com/cookiecutter/cookiecutter-django/pull/4890))
|
||||
|
||||
- Update crispy-bootstrap5 to 2024.2 ([#4891](https://github.com/cookiecutter/cookiecutter-django/pull/4891))
|
||||
|
||||
## 2024.02.24
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update coverage to 7.4.3 ([#4888](https://github.com/cookiecutter/cookiecutter-django/pull/4888))
|
||||
|
||||
## 2024.02.23
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Switch to local imports within app ([#4883](https://github.com/cookiecutter/cookiecutter-django/pull/4883))
|
||||
|
||||
- Install ruff extension in `devcontainer.json` ([#4887](https://github.com/cookiecutter/cookiecutter-django/pull/4887))
|
||||
|
||||
### Updated
|
||||
|
||||
- Bump webpack-dev-server to 5.0.2 ([#4875](https://github.com/cookiecutter/cookiecutter-django/pull/4875))
|
||||
|
||||
## 2024.02.21
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Switch to `celery.shared_task` to define tasks ([#4881](https://github.com/cookiecutter/cookiecutter-django/pull/4881))
|
||||
|
||||
- Replace usages of `get_user_model` by importing model directly ([#4879](https://github.com/cookiecutter/cookiecutter-django/pull/4879))
|
||||
|
||||
### Updated
|
||||
|
||||
- Auto-update pre-commit hooks ([#4873](https://github.com/cookiecutter/cookiecutter-django/pull/4873))
|
||||
|
||||
- Update pre-commit to 3.6.2 ([#4874](https://github.com/cookiecutter/cookiecutter-django/pull/4874))
|
||||
|
||||
- Update ruff to 0.2.2 ([#4871](https://github.com/cookiecutter/cookiecutter-django/pull/4871))
|
||||
|
||||
## 2024.02.19
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update sentry-sdk to 1.40.5 ([#4876](https://github.com/cookiecutter/cookiecutter-django/pull/4876))
|
||||
|
||||
## 2024.02.17
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update pytest to 8.0.1 ([#4870](https://github.com/cookiecutter/cookiecutter-django/pull/4870))
|
||||
|
||||
## 2024.02.16
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Speed up GitHub CI for Docker setup ([#4863](https://github.com/cookiecutter/cookiecutter-django/pull/4863))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Add link to the ruff repository in requirements ([#4866](https://github.com/cookiecutter/cookiecutter-django/pull/4866))
|
||||
|
||||
## 2024.02.13
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Ruff linting & formatting ([#4834](https://github.com/cookiecutter/cookiecutter-django/pull/4834))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update uvicorn to 0.27.1 ([#4848](https://github.com/cookiecutter/cookiecutter-django/pull/4848))
|
||||
|
||||
- Update sentry-sdk to 1.40.4 ([#4858](https://github.com/cookiecutter/cookiecutter-django/pull/4858))
|
||||
|
||||
- Bump traefik to 2.11.0 ([#4857](https://github.com/cookiecutter/cookiecutter-django/pull/4857))
|
||||
|
||||
- Auto-update pre-commit hooks ([#4855](https://github.com/cookiecutter/cookiecutter-django/pull/4855))
|
||||
|
||||
- Update black to 24.2.0 ([#4853](https://github.com/cookiecutter/cookiecutter-django/pull/4853))
|
||||
|
||||
## 2024.02.12
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update django-model-utils to 4.4.0 ([#4850](https://github.com/cookiecutter/cookiecutter-django/pull/4850))
|
||||
|
||||
- Update pre-commit to 3.6.1 ([#4849](https://github.com/cookiecutter/cookiecutter-django/pull/4849))
|
||||
|
||||
- Update django-upgrade to 1.16.0 ([#4851](https://github.com/cookiecutter/cookiecutter-django/pull/4851))
|
||||
|
||||
- Auto-update pre-commit hooks ([#4852](https://github.com/cookiecutter/cookiecutter-django/pull/4852))
|
||||
|
||||
## 2024.02.09
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update sentry-sdk to 1.40.3 ([#4847](https://github.com/cookiecutter/cookiecutter-django/pull/4847))
|
||||
|
||||
- Update django-allauth to 0.61.1 ([#4846](https://github.com/cookiecutter/cookiecutter-django/pull/4846))
|
||||
|
||||
- Update python-slugify to 8.0.4 ([#4844](https://github.com/cookiecutter/cookiecutter-django/pull/4844))
|
||||
|
||||
## 2024.02.08
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Bump python to 3.11.8 in compose/local/docs ([#4840](https://github.com/cookiecutter/cookiecutter-django/pull/4840))
|
||||
|
||||
- Bump python to 3.11.8 in compose/local/django ([#4841](https://github.com/cookiecutter/cookiecutter-django/pull/4841))
|
||||
|
||||
- Bump python to 3.11.8 in compose/production/django ([#4842](https://github.com/cookiecutter/cookiecutter-django/pull/4842))
|
||||
|
||||
## 2024.02.07
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Extend docker test with deploy check ([#4838](https://github.com/cookiecutter/cookiecutter-django/pull/4838))
|
||||
|
||||
- Generic UserManager ([#4836](https://github.com/cookiecutter/cookiecutter-django/pull/4836))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update django-allauth to 0.61.0 ([#4839](https://github.com/cookiecutter/cookiecutter-django/pull/4839))
|
||||
|
||||
- Bump gulp-postcss to 10.0.0 ([#4835](https://github.com/cookiecutter/cookiecutter-django/pull/4835))
|
||||
|
||||
- Update sentry-sdk to 1.40.2 ([#4837](https://github.com/cookiecutter/cookiecutter-django/pull/4837))
|
||||
|
||||
- Update django to 4.2.10 ([#4833](https://github.com/cookiecutter/cookiecutter-django/pull/4833))
|
||||
|
||||
## 2024.02.05
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update pytest to 8.0.0 ([#4813](https://github.com/cookiecutter/cookiecutter-django/pull/4813))
|
||||
|
||||
- Update pytest-sugar to 1.0.0 ([#4828](https://github.com/cookiecutter/cookiecutter-django/pull/4828))
|
||||
|
||||
- Update sphinx-autobuild to 2024.2.4 ([#4830](https://github.com/cookiecutter/cookiecutter-django/pull/4830))
|
||||
|
||||
- Update django-debug-toolbar to 4.3.0 ([#4829](https://github.com/cookiecutter/cookiecutter-django/pull/4829))
|
||||
|
||||
- Update psycopg to 3.1.18 ([#4831](https://github.com/cookiecutter/cookiecutter-django/pull/4831))
|
||||
|
||||
## 2024.01.31
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update python-slugify to 8.0.3 ([#4826](https://github.com/cookiecutter/cookiecutter-django/pull/4826))
|
||||
|
||||
## 2024.01.30
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update pytest-django to 4.8.0 ([#4823](https://github.com/cookiecutter/cookiecutter-django/pull/4823))
|
||||
|
||||
- Update sentry-sdk to 1.40.0 ([#4822](https://github.com/cookiecutter/cookiecutter-django/pull/4822))
|
||||
|
||||
- Update uvicorn to 0.27.0.post1 ([#4818](https://github.com/cookiecutter/cookiecutter-django/pull/4818))
|
||||
|
||||
## 2024.01.29
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Fix deprecation warning about renaming of `webpack_loader.loader` to `webpack_loader.loaders` ([#4815](https://github.com/cookiecutter/cookiecutter-django/pull/4815))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Update mention of coverage config file to `pyproject.toml` in documentation ([#4816](https://github.com/cookiecutter/cookiecutter-django/pull/4816))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update black to 24.1.1 ([#4814](https://github.com/cookiecutter/cookiecutter-django/pull/4814))
|
||||
|
||||
- Auto-update pre-commit hooks ([#4817](https://github.com/cookiecutter/cookiecutter-django/pull/4817))
|
||||
|
||||
## 2024.01.27
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Do not show webpack devserver overlay for warnings ([#4809](https://github.com/cookiecutter/cookiecutter-django/pull/4809))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update python-slugify to 8.0.2 ([#4805](https://github.com/cookiecutter/cookiecutter-django/pull/4805))
|
||||
|
||||
- Update coverage to 7.4.1 ([#4807](https://github.com/cookiecutter/cookiecutter-django/pull/4807))
|
||||
|
||||
## 2024.01.26
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update black to 24.1.0 ([#4806](https://github.com/cookiecutter/cookiecutter-django/pull/4806))
|
||||
|
||||
## 2024.01.25
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Replace custom static & media storage classes by passing options in the `STORAGES` setting ([#4803](https://github.com/cookiecutter/cookiecutter-django/pull/4803))
|
||||
|
||||
- Add registry to Docker images names ([#4804](https://github.com/cookiecutter/cookiecutter-django/pull/4804))
|
||||
|
||||
## 2024.01.24
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Migrate to the unified `STORAGES` setting added in Django 4.2 ([#4477](https://github.com/cookiecutter/cookiecutter-django/pull/4477))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update uvicorn to 0.27.0 ([#4800](https://github.com/cookiecutter/cookiecutter-django/pull/4800))
|
||||
|
||||
## 2024.01.21
|
||||
|
||||
|
||||
|
|
|
@ -18,20 +18,20 @@ This last step is very important, don't start developing from master, it'll caus
|
|||
|
||||
## Testing
|
||||
|
||||
You'll need to run the tests using Python 3.11. We recommend using [tox](https://tox.readthedocs.io/en/latest/) to run the tests. It will automatically create a fresh virtual environment and install our test dependencies, such as [pytest-cookies](https://pypi.python.org/pypi/pytest-cookies/) and [flake8](https://pypi.python.org/pypi/flake8/).
|
||||
You'll need to run the tests using Python 3.12. We recommend using [tox](https://tox.readthedocs.io/en/latest/) to run the tests. It will automatically create a fresh virtual environment and install our test dependencies, such as [pytest-cookies](https://pypi.python.org/pypi/pytest-cookies/) and [flake8](https://pypi.python.org/pypi/flake8/).
|
||||
|
||||
We'll also run the tests on GitHub actions when you send your pull request, but it's a good idea to run them locally before you send it.
|
||||
|
||||
### Installation
|
||||
|
||||
First, make sure that your version of Python is 3.11:
|
||||
First, make sure that your version of Python is 3.12:
|
||||
|
||||
```bash
|
||||
$ python --version
|
||||
Python 3.11.3
|
||||
Python 3.12.2
|
||||
```
|
||||
|
||||
Any version that starts with 3.11 will do. If you need to install it, you can get it from [python.org](https://www.python.org/downloads/).
|
||||
Any version that starts with 3.12 will do. If you need to install it, you can get it from [python.org](https://www.python.org/downloads/).
|
||||
|
||||
Then install `tox`, if not already installed:
|
||||
|
||||
|
|
|
@ -964,6 +964,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>henningbra</td>
|
||||
<td>
|
||||
<a href="https://github.com/henningbra">henningbra</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Henrique G. G. Pereira</td>
|
||||
<td>
|
||||
|
@ -1041,6 +1048,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JAEGYUN JUNG</td>
|
||||
<td>
|
||||
<a href="https://github.com/TGoddessana">TGoddessana</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jakub Boukal</td>
|
||||
<td>
|
||||
|
@ -1076,6 +1090,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jens Kaeske</td>
|
||||
<td>
|
||||
<a href="https://github.com/jkaeske">jkaeske</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jens Nilsson</td>
|
||||
<td>
|
||||
|
@ -1440,6 +1461,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Matthew Foster Walsh</td>
|
||||
<td>
|
||||
<a href="https://github.com/mfosterw">mfosterw</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Matthew Sisley</td>
|
||||
<td>
|
||||
|
@ -1475,13 +1503,6 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>mfosterw</td>
|
||||
<td>
|
||||
<a href="https://github.com/mfosterw">mfosterw</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Michael Gecht</td>
|
||||
<td>
|
||||
|
@ -1538,6 +1559,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mounir</td>
|
||||
<td>
|
||||
<a href="https://github.com/mounirmesselmeni">mounirmesselmeni</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>mozillazg</td>
|
||||
<td>
|
||||
|
@ -1636,6 +1664,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Paul Wulff</td>
|
||||
<td>
|
||||
<a href="https://github.com/mtmpaulwulff">mtmpaulwulff</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pawan Chaurasia</td>
|
||||
<td>
|
||||
|
@ -1811,6 +1846,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td>shywn_mrk</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simeon Emanuilov</td>
|
||||
<td>
|
||||
<a href="https://github.com/s-emanuilov">s-emanuilov</a>
|
||||
</td>
|
||||
<td>s_emanuilov</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simon Rey</td>
|
||||
<td>
|
||||
|
|
15
README.md
15
README.md
|
@ -20,7 +20,7 @@ production-ready Django projects quickly.
|
|||
## Features
|
||||
|
||||
- For Django 4.2
|
||||
- Works with Python 3.11
|
||||
- Works with Python 3.12
|
||||
- Renders Django projects with 100% starting test coverage
|
||||
- Twitter [Bootstrap](https://github.com/twbs/bootstrap) v5
|
||||
- [12-Factor](https://12factor.net) based settings via [django-environ](https://github.com/joke2k/django-environ)
|
||||
|
@ -51,7 +51,7 @@ _These features can be enabled during initial project setup._
|
|||
## Constraints
|
||||
|
||||
- Only maintained 3rd party libraries are used.
|
||||
- Uses PostgreSQL everywhere: 10 - 15 ([MySQL fork](https://github.com/mabdullahadeel/cookiecutter-django-mysql) also available).
|
||||
- Uses PostgreSQL everywhere: 12 - 16 ([MySQL fork](https://github.com/mabdullahadeel/cookiecutter-django-mysql) also available).
|
||||
- Environment variables for configuration (This won't work with Apache/mod_wsgi).
|
||||
|
||||
## Support this Project!
|
||||
|
@ -129,12 +129,11 @@ Answer the prompts with your own desired [options](http://cookiecutter-django.re
|
|||
Choose from 1, 2, 3 [1]: 1
|
||||
use_docker [n]: n
|
||||
Select postgresql_version:
|
||||
1 - 15
|
||||
2 - 14
|
||||
3 - 13
|
||||
4 - 12
|
||||
5 - 11
|
||||
6 - 10
|
||||
1 - 16
|
||||
2 - 15
|
||||
3 - 14
|
||||
4 - 13
|
||||
5 - 12
|
||||
Choose from 1, 2, 3, 4, 5 [1]: 1
|
||||
Select cloud_provider:
|
||||
1 - AWS
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"windows": "n",
|
||||
"editor": ["None", "PyCharm", "VS Code"],
|
||||
"use_docker": "n",
|
||||
"postgresql_version": ["15", "14", "13", "12", "11", "10"],
|
||||
"postgresql_version": ["16", "15", "14", "13", "12"],
|
||||
"cloud_provider": ["AWS", "GCP", "Azure", "None"],
|
||||
"mail_service": [
|
||||
"Mailgun",
|
||||
|
|
|
@ -37,7 +37,7 @@ Make sure your project is fully committed and pushed up to Bitbucket or Github o
|
|||
mkvirtualenv --python=/usr/bin/python3.10 my-project-name
|
||||
pip install -r requirements/production.txt # may take a few minutes
|
||||
|
||||
.. note:: We're creating the virtualenv using Python 3.10 (``--python=/usr/bin/python3.10```), although Cookiecutter Django generates a project for Python 3.11. This is because, at time of writing, PythonAnywhere only supports Python 3.10. It shouldn't be a problem, but if is, you may try changing the Python version to 3.11 and see if it works. If it does, please let us know, or even better, submit a pull request to update this section.
|
||||
.. note:: We're creating the virtualenv using Python 3.10 (``--python=/usr/bin/python3.10```), although Cookiecutter Django generates a project for Python 3.12. This is because, at time of writing, PythonAnywhere only supports Python 3.10. It shouldn't be a problem, but if is, you may try changing the Python version to 3.12 and see if it works. If it does, please let us know, or even better, submit a pull request to update this section.
|
||||
|
||||
Setting environment variables in the console
|
||||
--------------------------------------------
|
||||
|
|
|
@ -65,6 +65,13 @@ To run in a detached (background) mode, just::
|
|||
|
||||
$ docker compose up -d
|
||||
|
||||
These commands don't run the docs service. In order to run docs service you can run::
|
||||
|
||||
$ docker compose -f docs.yml up
|
||||
|
||||
To run the docs with local services just use::
|
||||
|
||||
$ docker compose -f local.yml -f docs.yml up
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ Setting Up Development Environment
|
|||
|
||||
Make sure to have the following on your host:
|
||||
|
||||
* Python 3.11
|
||||
* Python 3.12
|
||||
* PostgreSQL_.
|
||||
* Redis_, if using Celery
|
||||
* Cookiecutter_
|
||||
|
@ -18,7 +18,7 @@ First things first.
|
|||
|
||||
#. Create a virtualenv: ::
|
||||
|
||||
$ python3.11 -m venv <virtual env path>
|
||||
$ python3.12 -m venv <virtual env path>
|
||||
|
||||
#. Activate the virtualenv you have just created: ::
|
||||
|
||||
|
|
|
@ -104,3 +104,24 @@ Remove Backup
|
|||
To remove backup you can use the ``rmbackup`` command. This will remove the backup from the ``/backups`` directory. ::
|
||||
|
||||
$ docker compose -f local.yml exec postgres rmbackup backup_2018_03_13T09_05_07.sql.gz
|
||||
|
||||
|
||||
Upgrading PostgreSQL
|
||||
----------------------------------
|
||||
|
||||
Upgrading PostgreSQL in your project requires a series of carefully executed steps. Start by halting all containers, excluding the postgres container. Following this, create a backup and proceed to remove the outdated data volume. ::
|
||||
|
||||
$ docker compose -f local.yml down
|
||||
$ docker compose -f local.yml up -d postgres
|
||||
$ docker compose -f local.yml run --rm postgres backup
|
||||
$ docker compose -f local.yml down
|
||||
$ docker volume rm my_project_postgres_data
|
||||
|
||||
.. note:: Neglecting to remove the old data volume may lead to issues, such as the new postgres container failing to start with errors like ``FATAL: database files are incompatible with server``, and ``could not translate host name "postgres" to address: Name or service not known``.
|
||||
|
||||
To complete the upgrade, update the PostgreSQL version in the corresponding Dockerfile (e.g. ``compose/production/postgres/Dockerfile``) and build a new version of PostgreSQL. ::
|
||||
|
||||
$ docker compose -f local.yml build postgres
|
||||
$ docker compose -f local.yml up -d postgres
|
||||
$ docker compose -f local.yml run --rm postgres restore backup_2018_03_13T09_05_07.sql.gz
|
||||
$ docker compose -f local.yml up -d
|
||||
|
|
|
@ -22,6 +22,6 @@ TODO
|
|||
Why doesn't this follow the layout from Two Scoops of Django?
|
||||
-------------------------------------------------------------
|
||||
|
||||
You may notice that some elements of this project do not exactly match what we describe in chapter 3 of `Two Scoops of Django 1.11`_. The reason for that is this project, amongst other things, serves as a test bed for trying out new ideas and concepts. Sometimes they work, sometimes they don't, but the end result is that it won't necessarily match precisely what is described in the book I co-authored.
|
||||
You may notice that some elements of this project do not exactly match what we describe in chapter 3 of `Two Scoops of Django 3.x`_. The reason for that is this project, amongst other things, serves as a test bed for trying out new ideas and concepts. Sometimes they work, sometimes they don't, but the end result is that it won't necessarily match precisely what is described in the book I co-authored.
|
||||
|
||||
.. _Two Scoops of Django 1.11: https://www.feldroy.com/collections/django/products/two-scoops-of-django-1-11
|
||||
.. _Two Scoops of Django 3.x: https://www.feldroy.com/books/two-scoops-of-django-3-x
|
||||
|
|
|
@ -28,6 +28,7 @@ Contents
|
|||
faq
|
||||
troubleshooting
|
||||
contributing
|
||||
maintainer-guide
|
||||
|
||||
Indices and tables
|
||||
------------------
|
||||
|
|
|
@ -4,40 +4,30 @@ Linters
|
|||
.. index:: linters
|
||||
|
||||
|
||||
flake8
|
||||
ruff
|
||||
------
|
||||
|
||||
To run flake8: ::
|
||||
Ruff is a Python linter and code formatter, written in Rust.
|
||||
It is a aggregation of flake8, pylint, pyupgrade and many more.
|
||||
|
||||
$ flake8
|
||||
Ruff comes with a linter (``ruff check``) and a formatter (``ruff format``).
|
||||
The linter is a wrapper around flake8, pylint, and other linters,
|
||||
and the formatter is a wrapper around black, isort, and other formatters.
|
||||
|
||||
The config for flake8 is located in setup.cfg. It specifies:
|
||||
To run ruff without modifying your files: ::
|
||||
|
||||
* Set max line length to 120 chars
|
||||
* Exclude ``.tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules``
|
||||
$ ruff format --diff .
|
||||
$ ruff check .
|
||||
|
||||
pylint
|
||||
------
|
||||
Ruff is capable of fixing most of the problems it encounters.
|
||||
Be sure you commit first before running `ruff` so you can restore to a savepoint (and amend afterwards to prevent a double commit. : ::
|
||||
|
||||
To run pylint: ::
|
||||
$ ruff format .
|
||||
$ ruff check --fix .
|
||||
# be careful with the --unsafe-fixes option, it can break your code
|
||||
$ ruff check --fix --unsafe-fixes .
|
||||
|
||||
$ pylint <python files that you wish to lint>
|
||||
|
||||
The config for pylint is located in .pylintrc. It specifies:
|
||||
|
||||
* Use the pylint_django plugin. If using Celery, also use pylint_celery.
|
||||
* Set max line length to 120 chars
|
||||
* Disable linting messages for missing docstring and invalid name
|
||||
* max-parents=13
|
||||
|
||||
pycodestyle
|
||||
-----------
|
||||
|
||||
This is included in flake8's checks, but you can also run it separately to see a more detailed report: ::
|
||||
|
||||
$ pycodestyle <python files that you wish to lint>
|
||||
|
||||
The config for pycodestyle is located in setup.cfg. It specifies:
|
||||
|
||||
* Set max line length to 120 chars
|
||||
* Exclude ``.tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules``
|
||||
The config for ruff is located in pyproject.toml.
|
||||
On of the most important option is `tool.ruff.lint.select`.
|
||||
`select` determines which linters are run. In example, `DJ <https://docs.astral.sh/ruff/rules/#flake8-django-dj>`_ refers to flake8-django.
|
||||
For a full list of available linters, see `https://docs.astral.sh/ruff/rules/ <https://docs.astral.sh/ruff/rules/>`_
|
||||
|
|
104
docs/maintainer-guide.md
Normal file
104
docs/maintainer-guide.md
Normal file
|
@ -0,0 +1,104 @@
|
|||
# Maintainer guide
|
||||
|
||||
This document is intended for maintainers of the template.
|
||||
|
||||
## Automated updates
|
||||
|
||||
We use 2 separate services to keep our dependencies up-to-date:
|
||||
|
||||
- Dependabot, which manages updates of Python deps of the template, GitHub actions, npm packages and Docker images.
|
||||
- PyUp, which manages the Python deps for the generated project.
|
||||
|
||||
We don't use Dependabot for the generated project deps because our requirements files are templated, and Dependabot fails to parse them. PyUp is -AFAIK- the only service out there that supports having Jinja tags in the requirements file.
|
||||
|
||||
Updates for the template should be labelled as `project infrastructure` while the ones about the generated project should be labelled as `update`. This is use to work in conjunction with our changelog script (see later).
|
||||
|
||||
## Automation scripts
|
||||
|
||||
We have a few workflows which have been automated over time. They usually run using GitHub actions and might need a few small manual actions to work nicely. Some have a few limitations which we should document here.
|
||||
|
||||
### CI
|
||||
|
||||
`ci.yml`
|
||||
|
||||
The CI workflow tries to cover 2 main aspects of the template:
|
||||
|
||||
- Check all combinations to make sure that valid files are generated with no major linting issues. Issues which are fixed by an auto-formatter after generation aren't considered major, and only aim for best effort. This is under the `test` job.
|
||||
- Run more in-depth tests on a few combinations, by installing dependencies, running type checker and the test suite of the generated project. We try to cover docker (`docker` job) and non-docker (`bare` job) setups.
|
||||
|
||||
We also run the deployment checks, but we don't do much more beyond that for testing the production setup.
|
||||
|
||||
### Django issue checker
|
||||
|
||||
`django-issue-checker.yml`
|
||||
|
||||
This workflow runs daily, on schedule, and checks if there is a new major version of Django (not in the pure SemVer sense) released that we are not running, and list our dependencies compatibility.
|
||||
|
||||
For example, at time of writing, we use Django 4.2, but the latest version of Django is 5.0, so the workflow created a ["Django 5.0" issue](https://github.com/cookiecutter/cookiecutter-django/issues/4724) in GitHub, with a compatibility table and keeps it up to date every day.
|
||||
|
||||
#### Limitations
|
||||
|
||||
Here are a few current and past limitations of the script
|
||||
|
||||
- When a new dependency is added to the template, the script fails to update an existing issue
|
||||
- Not sure what happens when a deps is removed
|
||||
- ~~Unable to parse classifiers without minor version~~
|
||||
- ~~Creates an issue even if we are on the latest version~~
|
||||
|
||||
### Issue manager
|
||||
|
||||
`issue-manager.yml`
|
||||
|
||||
A workflow that uses [Sebastian Ramirez' issue-manager](https://github.com/tiangolo/issue-manager) to help us automate issue management. The tag line from the repo explains it well:
|
||||
|
||||
> Automatically close issues or Pull Requests that have a label, after a custom delay, if no one replies back.
|
||||
|
||||
It runs on a schedule as well as when some actions are taken on issues and pull requests.
|
||||
|
||||
We wait 10 days before closing issues, and we have a few customised reasons, which are configured in the workflow itself. The config should be fairly self-explanatory.
|
||||
|
||||
### Pre-commit auto-update
|
||||
|
||||
`pre-commit-autoupdate.yml`
|
||||
|
||||
Run daily, to do `pre-commit autoupdate` on the template as well as the generated project, and opens a pull request with the changes.
|
||||
|
||||
#### Limitations
|
||||
|
||||
- The PR is open as GitHub action which means that CI does NOT run. The documentation for create-pull-request action [explains why](https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#triggering-further-workflow-runs).
|
||||
- Some hooks are also installed as local dependencies (via `requirements/local.txt`), but these are updated separately via PyUP.
|
||||
|
||||
### Update changelog
|
||||
|
||||
`update-changelog.yml`
|
||||
|
||||
Run daily at 2AM to update our changelog and create a GitHub release. This runs a custom script which:
|
||||
|
||||
- List all pull requests merged the day before
|
||||
- The release name is calendar based, so `YYYY.MM.DD`
|
||||
- For each PR:
|
||||
- Get the PR title to summarize the change
|
||||
- Look at the PR labels to classify it in a section of the release notes:
|
||||
- anything labelled `project infrastructure` is excluded
|
||||
- label `update` goes in section "Updated"
|
||||
- label `bug` goes in section "Fixed"
|
||||
- label `docs` goes in section "Documentation"
|
||||
- Default to section "Changed"
|
||||
|
||||
With that in mind, when merging changes, it's a good idea to set the labels and rename the PR title to give a good summary of the change, in the context of the changelog.
|
||||
|
||||
#### Limitations
|
||||
|
||||
- Dependabot updates for npm & Docker have a verbose title, try to rename them to be more readable: `Bump webpack-dev-server from 4.15.1 to 5.0.2 in /{{cookiecutter.project_slug}}` -> `Bump webpack-dev-server to 5.0.2`
|
||||
- ~~Dependencies updates for the template repo (tox, cookiecutter, etc...) don't need to appear in changelog, and need to be labelled as `project infrastructure` manually. By default, they come from PyUp labelled as `update`.~~
|
||||
|
||||
### Update contributors
|
||||
|
||||
`update-contributors.yml`
|
||||
|
||||
Runs on each push to master branch. List the 5 most recently merged pull requests and extract their author. If any of the authors is a new one, updates the `.github/contributors.json`, regenerate the `CONTRIBUTORS.md` from it, and push back the changes to master.
|
||||
|
||||
#### Limitations
|
||||
|
||||
- If you merge a pull request from a new contributor, and merge another one right after, the push to master will fail as the remote will be out of date.
|
||||
- If you merge more than 5 pull requests in a row like this, the new contributor might fail to be added.
|
|
@ -59,12 +59,11 @@ use_docker:
|
|||
postgresql_version:
|
||||
Select a PostgreSQL_ version to use. The choices are:
|
||||
|
||||
1. 15
|
||||
2. 14
|
||||
3. 13
|
||||
4. 12
|
||||
5. 11
|
||||
6. 10
|
||||
1. 16
|
||||
2. 15
|
||||
3. 14
|
||||
4. 13
|
||||
5. 12
|
||||
|
||||
cloud_provider:
|
||||
Select a cloud provider for static & media files. The choices are:
|
||||
|
|
|
@ -43,7 +43,7 @@ If you're running the project locally with Docker, use these commands instead: :
|
|||
|
||||
At the root of the project folder, you will find the `pytest.ini` file. You can use this to customize_ the ``pytest`` to your liking.
|
||||
|
||||
There is also the `.coveragerc`. This is the configuration file for the ``coverage`` tool. You can find out more about `configuring`_ ``coverage``.
|
||||
The configuration for ``coverage`` can be found in ``pyproject.toml``. You can find out more about `configuring`_ ``coverage``.
|
||||
|
||||
.. seealso::
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ NOTE:
|
|||
TODO: restrict Cookiecutter Django project initialization to
|
||||
Python 3.x environments only
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import json
|
||||
|
@ -429,10 +430,6 @@ def remove_drf_starter_files():
|
|||
os.remove(os.path.join("{{cookiecutter.project_slug}}", "users", "tests", "test_swagger.py"))
|
||||
|
||||
|
||||
def remove_storages_module():
|
||||
os.remove(os.path.join("{{cookiecutter.project_slug}}", "utils", "storages.py"))
|
||||
|
||||
|
||||
def main():
|
||||
debug = "{{ cookiecutter.debug }}".lower() == "y"
|
||||
|
||||
|
@ -499,7 +496,6 @@ def main():
|
|||
WARNING + "You chose to not use any cloud providers nor Docker, "
|
||||
"media files won't be served in production." + TERMINATOR
|
||||
)
|
||||
remove_storages_module()
|
||||
|
||||
if "{{ cookiecutter.use_celery }}".lower() == "n":
|
||||
remove_celery_files()
|
||||
|
|
|
@ -7,6 +7,7 @@ NOTE:
|
|||
TODO: restrict Cookiecutter Django project initialization
|
||||
to Python 3.x environments only
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
|
@ -38,7 +39,7 @@ if "{{ cookiecutter.use_docker }}".lower() == "n":
|
|||
if python_major_version == 2:
|
||||
print(
|
||||
WARNING + "You're running cookiecutter under Python 2, but the generated "
|
||||
"project requires Python 3.11+. Do you want to proceed (y/n)? " + TERMINATOR
|
||||
"project requires Python 3.12+. Do you want to proceed (y/n)? " + TERMINATOR
|
||||
)
|
||||
yes_options, no_options = frozenset(["y"]), frozenset(["n"])
|
||||
while True:
|
||||
|
|
|
@ -15,7 +15,7 @@ norecursedirs = [
|
|||
# ==== black ====
|
||||
[tool.black]
|
||||
line-length = 119
|
||||
target-version = ['py311']
|
||||
target-version = ['py312']
|
||||
|
||||
|
||||
# ==== isort ====
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
cookiecutter==2.5.0
|
||||
cookiecutter==2.6.0
|
||||
sh==2.0.6; sys_platform != "win32"
|
||||
binaryornot==0.4.4
|
||||
|
||||
# Code quality
|
||||
# ------------------------------------------------------------------------------
|
||||
black==23.12.1
|
||||
isort==5.13.2
|
||||
flake8==7.0.0
|
||||
django-upgrade==1.15.0
|
||||
ruff==0.3.3
|
||||
django-upgrade==1.16.0
|
||||
djlint==1.34.1
|
||||
pre-commit==3.6.0
|
||||
pre-commit==3.6.2
|
||||
|
||||
# Testing
|
||||
# ------------------------------------------------------------------------------
|
||||
tox==4.12.1
|
||||
pytest==7.4.4
|
||||
tox==4.14.1
|
||||
pytest==8.1.1
|
||||
pytest-xdist==3.5.0
|
||||
pytest-cookies==0.7.0
|
||||
pytest-instafail==0.5.0
|
||||
|
@ -22,7 +20,7 @@ pyyaml==6.0.1
|
|||
|
||||
# Scripting
|
||||
# ------------------------------------------------------------------------------
|
||||
PyGithub==2.1.1
|
||||
gitpython==3.1.41
|
||||
PyGithub==2.2.0
|
||||
gitpython==3.1.42
|
||||
jinja2==3.1.3
|
||||
requests==2.31.0
|
||||
|
|
|
@ -6,6 +6,7 @@ patches, only comparing major and minor version numbers.
|
|||
This script handles when there are multiple Django versions that need
|
||||
to keep up to date.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
|
|
@ -40,8 +40,8 @@ def iter_recent_authors():
|
|||
"""
|
||||
Fetch users who opened recently merged pull requests.
|
||||
|
||||
Use Github API to fetch recent authors rather than
|
||||
git CLI to work with Github usernames.
|
||||
Use GitHub API to fetch recent authors rather than
|
||||
git CLI to work with GitHub usernames.
|
||||
"""
|
||||
repo = Github(login_or_token=GITHUB_TOKEN, per_page=5).get_repo(GITHUB_REPO)
|
||||
recent_pulls = repo.get_pulls(state="closed", sort="updated", direction="desc").get_page(0)
|
||||
|
|
4
setup.py
4
setup.py
|
@ -5,7 +5,7 @@ except ImportError:
|
|||
from distutils.core import setup
|
||||
|
||||
# We use calendar versioning
|
||||
version = "2024.01.21"
|
||||
version = "2024.03.21"
|
||||
|
||||
with open("README.md") as readme_file:
|
||||
long_description = readme_file.read()
|
||||
|
@ -30,7 +30,7 @@ setup(
|
|||
"License :: OSI Approved :: BSD License",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"Topic :: Software Development",
|
||||
],
|
||||
|
|
|
@ -56,12 +56,11 @@ SUPPORTED_COMBINATIONS = [
|
|||
{"editor": "VS Code"},
|
||||
{"use_docker": "y"},
|
||||
{"use_docker": "n"},
|
||||
{"postgresql_version": "16"},
|
||||
{"postgresql_version": "15"},
|
||||
{"postgresql_version": "14"},
|
||||
{"postgresql_version": "13"},
|
||||
{"postgresql_version": "12"},
|
||||
{"postgresql_version": "11"},
|
||||
{"postgresql_version": "10"},
|
||||
{"cloud_provider": "AWS", "use_whitenoise": "y"},
|
||||
{"cloud_provider": "AWS", "use_whitenoise": "n"},
|
||||
{"cloud_provider": "GCP", "use_whitenoise": "y"},
|
||||
|
@ -179,28 +178,25 @@ def test_project_generation(cookies, context, context_override):
|
|||
|
||||
|
||||
@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id)
|
||||
def test_flake8_passes(cookies, context_override):
|
||||
"""Generated project should pass flake8."""
|
||||
def test_ruff_check_passes(cookies, context_override):
|
||||
"""Generated project should pass ruff check."""
|
||||
result = cookies.bake(extra_context=context_override)
|
||||
|
||||
try:
|
||||
sh.flake8(_cwd=str(result.project_path))
|
||||
sh.ruff("check", ".", _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_black_passes(cookies, context_override):
|
||||
"""Check whether generated project passes black style."""
|
||||
def test_ruff_format_passes(cookies, context_override):
|
||||
"""Check whether generated project passes ruff format."""
|
||||
result = cookies.bake(extra_context=context_override)
|
||||
|
||||
try:
|
||||
sh.black(
|
||||
"--check",
|
||||
"--diff",
|
||||
"--exclude",
|
||||
"migrations",
|
||||
sh.ruff(
|
||||
"format",
|
||||
".",
|
||||
_cwd=str(result.project_path),
|
||||
)
|
||||
|
@ -286,7 +282,7 @@ def test_travis_invokes_pytest(cookies, context, use_docker, expected_test_scrip
|
|||
with open(f"{result.project_path}/.travis.yml") as travis_yml:
|
||||
try:
|
||||
yml = yaml.safe_load(travis_yml)["jobs"]["include"]
|
||||
assert yml[0]["script"] == ["flake8"]
|
||||
assert yml[0]["script"] == ["ruff check ."]
|
||||
assert yml[1]["script"] == [expected_test_script]
|
||||
except yaml.YAMLError as e:
|
||||
pytest.fail(str(e))
|
||||
|
|
|
@ -30,10 +30,20 @@ docker compose -f local.yml run django python manage.py makemigrations --dry-run
|
|||
docker compose -f local.yml run django python manage.py makemessages --all
|
||||
|
||||
# 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 \
|
||||
-e DJANGO_SECRET_KEY="$(openssl rand -base64 64)" \
|
||||
-e REDIS_URL=redis://redis:6379/0 \
|
||||
-e CELERY_BROKER_URL=redis://redis:6379/0 \
|
||||
-e DJANGO_AWS_ACCESS_KEY_ID=x \
|
||||
-e DJANGO_AWS_SECRET_ACCESS_KEY=x \
|
||||
-e DJANGO_AWS_STORAGE_BUCKET_NAME=x \
|
||||
-e DJANGO_ADMIN_URL=x \
|
||||
-e MAILGUN_API_KEY=x \
|
||||
-e MAILGUN_DOMAIN=x \
|
||||
django python manage.py check --settings=config.settings.production --deploy --database default --fail-level WARNING
|
||||
|
||||
# Generate the HTML for the documentation
|
||||
docker compose -f local.yml run docs make html
|
||||
docker compose -f docs.yml run docs make html
|
||||
|
||||
# Run npm build script if package.json is present
|
||||
if [ -f "package.json" ]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"""Unit tests for the hooks"""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
|
|
2
tox.ini
2
tox.ini
|
@ -1,6 +1,6 @@
|
|||
[tox]
|
||||
skipsdist = true
|
||||
envlist = py311,black-template
|
||||
envlist = py312,black-template
|
||||
|
||||
[testenv]
|
||||
deps = -rrequirements.txt
|
||||
|
|
|
@ -35,24 +35,13 @@
|
|||
"analysis.typeCheckingMode": "basic",
|
||||
"defaultInterpreterPath": "/usr/local/bin/python",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": true
|
||||
"source.organizeImports": "always"
|
||||
},
|
||||
// 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",
|
||||
"editor.defaultFormatter": "charliermarsh.ruff",
|
||||
"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
|
||||
|
@ -65,8 +54,7 @@
|
|||
// python
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"ms-python.isort",
|
||||
"ms-python.black-formatter",
|
||||
"charliermarsh.ruff",
|
||||
// django
|
||||
"batisteo.vscode-django"
|
||||
]
|
||||
|
|
|
@ -13,7 +13,7 @@ environment:
|
|||
steps:
|
||||
- name: lint
|
||||
pull: if-not-exists
|
||||
image: python:3.11
|
||||
image: python:3.12
|
||||
environment:
|
||||
PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
|
||||
volumes:
|
||||
|
@ -32,11 +32,12 @@ steps:
|
|||
DATABASE_URL: pgsql://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres/$POSTGRES_DB
|
||||
commands:
|
||||
- docker-compose -f local.yml build
|
||||
- docker-compose -f docs.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
|
||||
image: python:3.12
|
||||
commands:
|
||||
- pip install -r requirements/local.txt
|
||||
- pytest
|
||||
|
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
python-version: '3.12'
|
||||
|
||||
{%- if cookiecutter.open_source_license != 'Not open source' %}
|
||||
# Consider using pre-commit.ci for open source project
|
||||
|
@ -36,7 +36,7 @@ jobs:
|
|||
- name: Run pre-commit
|
||||
uses: pre-commit/action@v3.0.0
|
||||
|
||||
# With no caching at all the entire ci process takes 4m 30s to complete!
|
||||
# With no caching at all the entire ci process takes 3m to complete!
|
||||
pytest:
|
||||
runs-on: ubuntu-latest
|
||||
{%- if cookiecutter.use_docker == 'n' %}
|
||||
|
@ -69,7 +69,8 @@ jobs:
|
|||
{%- if cookiecutter.use_docker == 'y' %}
|
||||
|
||||
- name: Build the Stack
|
||||
run: docker compose -f local.yml build
|
||||
run: docker compose -f local.yml build django
|
||||
run: docker compose -f local.yml build docs
|
||||
|
||||
- name: Run DB Migrations
|
||||
run: docker compose -f local.yml run --rm django python manage.py migrate
|
||||
|
@ -84,7 +85,7 @@ jobs:
|
|||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
python-version: '3.12'
|
||||
cache: pip
|
||||
cache-dependency-path: |
|
||||
requirements/base.txt
|
||||
|
|
|
@ -13,7 +13,7 @@ variables:
|
|||
|
||||
precommit:
|
||||
stage: lint
|
||||
image: python:3.11
|
||||
image: python:3.12
|
||||
variables:
|
||||
PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
|
||||
cache:
|
||||
|
@ -34,13 +34,14 @@ pytest:
|
|||
- docker:dind
|
||||
before_script:
|
||||
- docker compose -f local.yml build
|
||||
- docker compose -f docs.yml build
|
||||
# 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 up -d
|
||||
script:
|
||||
- docker compose -f local.yml run django pytest
|
||||
{%- else %}
|
||||
image: python:3.11
|
||||
image: python:3.12
|
||||
tags:
|
||||
- python
|
||||
services:
|
||||
|
|
|
@ -2,7 +2,7 @@ exclude: '^docs/|/migrations/|devcontainer.json'
|
|||
default_stages: [commit]
|
||||
|
||||
default_language_version:
|
||||
python: python3.11
|
||||
python: python3.12
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
|
@ -32,31 +32,20 @@ repos:
|
|||
exclude: '{{cookiecutter.project_slug}}/templates/'
|
||||
|
||||
- repo: https://github.com/adamchainz/django-upgrade
|
||||
rev: '1.15.0'
|
||||
rev: '1.16.0'
|
||||
hooks:
|
||||
- id: django-upgrade
|
||||
args: ['--target-version', '4.2']
|
||||
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.15.0
|
||||
# Run the Ruff linter.
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.3.3
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py311-plus]
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.12.1
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.13.2
|
||||
hooks:
|
||||
- id: isort
|
||||
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 7.0.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
# Linter
|
||||
- id: ruff
|
||||
args: [--fix, --exit-non-zero-on-fix]
|
||||
# Formatter
|
||||
- id: ruff-format
|
||||
|
||||
- repo: https://github.com/Riverside-Healthcare/djLint
|
||||
rev: v1.34.1
|
||||
|
|
|
@ -8,7 +8,7 @@ version: 2
|
|||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: '3.11'
|
||||
python: '3.12'
|
||||
|
||||
# Build documentation in the docs/ directory with Sphinx
|
||||
sphinx:
|
||||
|
|
|
@ -2,7 +2,7 @@ dist: focal
|
|||
|
||||
language: python
|
||||
python:
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
|
||||
services:
|
||||
- {% if cookiecutter.use_docker == 'y' %}docker{% else %}postgresql{% endif %}
|
||||
|
@ -10,9 +10,9 @@ jobs:
|
|||
include:
|
||||
- name: "Linter"
|
||||
before_script:
|
||||
- pip install -q flake8
|
||||
- pip install -q ruff
|
||||
script:
|
||||
- "flake8"
|
||||
- ruff check .
|
||||
|
||||
- name: "Django Test"
|
||||
{%- if cookiecutter.use_docker == 'y' %}
|
||||
|
@ -20,11 +20,12 @@ jobs:
|
|||
- docker compose -v
|
||||
- docker -v
|
||||
- docker compose -f local.yml build
|
||||
- docker compose -f docs.yml build
|
||||
# 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 up -d
|
||||
script:
|
||||
- "docker compose -f local.yml run django pytest"
|
||||
- docker compose -f local.yml run django pytest
|
||||
after_failure:
|
||||
- docker compose -f local.yml logs
|
||||
{%- else %}
|
||||
|
@ -37,9 +38,9 @@ jobs:
|
|||
- sudo apt-get install -qq libsqlite3-dev libxml2 libxml2-dev libssl-dev libbz2-dev wget curl llvm
|
||||
language: python
|
||||
python:
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
install:
|
||||
- pip install -r requirements/local.txt
|
||||
script:
|
||||
- "pytest"
|
||||
- pytest
|
||||
{%- endif %}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{{ cookiecutter.description }}
|
||||
|
||||
[](https://github.com/cookiecutter/cookiecutter-django/)
|
||||
[](https://github.com/ambv/black)
|
||||
[](https://github.com/astral-sh/ruff)
|
||||
|
||||
{%- if cookiecutter.open_source_license != "Not open source" %}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# define an alias for the specific python version used in this file.
|
||||
FROM python:3.11.7-slim-bookworm as python
|
||||
FROM docker.io/python:3.12.2-slim-bookworm as python
|
||||
|
||||
# Python build stage
|
||||
FROM python as python-build-stage
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# define an alias for the specific python version used in this file.
|
||||
FROM python:3.11.7-slim-bookworm as python
|
||||
FROM docker.io/python:3.12.2-slim-bookworm as python
|
||||
|
||||
|
||||
# Python build stage
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM node:20-bookworm-slim
|
||||
FROM docker.io/node:20-bookworm-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM garland/aws-cli-docker:1.16.140
|
||||
FROM docker.io/garland/aws-cli-docker:1.16.140
|
||||
|
||||
COPY ./compose/production/aws/maintenance /usr/local/bin/maintenance
|
||||
COPY ./compose/production/postgres/maintenance/_sourced /usr/local/bin/maintenance/_sourced
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% if cookiecutter.frontend_pipeline in ['Gulp', 'Webpack'] -%}
|
||||
FROM node:20-bookworm-slim as client-builder
|
||||
FROM docker.io/node:20-bookworm-slim as client-builder
|
||||
|
||||
ARG APP_HOME=/app
|
||||
WORKDIR ${APP_HOME}
|
||||
|
@ -25,7 +25,7 @@ RUN npm run build
|
|||
|
||||
{%- endif %}
|
||||
# define an alias for the specific python version used in this file.
|
||||
FROM python:3.11.7-slim-bookworm as python
|
||||
FROM docker.io/python:3.12.2-slim-bookworm as python
|
||||
|
||||
# Python build stage
|
||||
FROM python as python-build-stage
|
||||
|
@ -117,7 +117,7 @@ COPY --chown=django:django . ${APP_HOME}
|
|||
{%- endif %}
|
||||
|
||||
# make django owner of the WORKDIR directory as well.
|
||||
RUN chown django:django ${APP_HOME}
|
||||
RUN chown -R django:django ${APP_HOME}
|
||||
|
||||
USER django
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
FROM nginx:1.17.8-alpine
|
||||
FROM docker.io/nginx:1.17.8-alpine
|
||||
COPY ./compose/production/nginx/default.conf /etc/nginx/conf.d/default.conf
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM postgres:{{ cookiecutter.postgresql_version }}
|
||||
FROM docker.io/postgres:{{ cookiecutter.postgresql_version }}
|
||||
|
||||
COPY ./compose/production/postgres/maintenance /usr/local/bin/maintenance
|
||||
RUN chmod +x /usr/local/bin/maintenance/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM traefik:2.10.7
|
||||
FROM docker.io/traefik:2.11.0
|
||||
RUN mkdir -p /etc/traefik/acme \
|
||||
&& touch /etc/traefik/acme/acme.json \
|
||||
&& chmod 600 /etc/traefik/acme/acme.json
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
from django.conf import settings
|
||||
from rest_framework.routers import DefaultRouter, SimpleRouter
|
||||
from rest_framework.routers import DefaultRouter
|
||||
from rest_framework.routers import SimpleRouter
|
||||
|
||||
from {{ cookiecutter.project_slug }}.users.api.views import UserViewSet
|
||||
|
||||
if settings.DEBUG:
|
||||
router = DefaultRouter()
|
||||
else:
|
||||
router = SimpleRouter()
|
||||
router = DefaultRouter() if settings.DEBUG else SimpleRouter()
|
||||
|
||||
router.register("users", UserViewSet)
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# ruff: noqa
|
||||
"""
|
||||
ASGI config for {{ cookiecutter.project_name }} project.
|
||||
|
||||
|
@ -7,6 +8,7 @@ For more information on this file, see
|
|||
https://docs.djangoproject.com/en/dev/howto/deployment/asgi/
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
@ -28,7 +30,7 @@ django_application = get_asgi_application()
|
|||
# application = HelloWorldApplication(application)
|
||||
|
||||
# Import websocket application here, so apps from django_application are loaded first
|
||||
from config.websocket import websocket_application # noqa isort:skip
|
||||
from config.websocket import websocket_application
|
||||
|
||||
|
||||
async def application(scope, receive, send):
|
||||
|
@ -37,4 +39,5 @@ async def application(scope, receive, send):
|
|||
elif scope["type"] == "websocket":
|
||||
await websocket_application(scope, receive, send)
|
||||
else:
|
||||
raise NotImplementedError(f"Unknown scope type {scope['type']}")
|
||||
msg = f"Unknown scope type {scope['type']}"
|
||||
raise NotImplementedError(msg)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""
|
||||
Base settings to build other settings files upon.
|
||||
"""
|
||||
# ruff: noqa: ERA001, E501
|
||||
"""Base settings to build other settings files upon."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import environ
|
||||
|
@ -84,6 +84,7 @@ THIRD_PARTY_APPS = [
|
|||
"crispy_bootstrap5",
|
||||
"allauth",
|
||||
"allauth.account",
|
||||
"allauth.mfa",
|
||||
"allauth.socialaccount",
|
||||
{%- if cookiecutter.use_celery == 'y' %}
|
||||
"django_celery_beat",
|
||||
|
@ -139,7 +140,9 @@ PASSWORD_HASHERS = [
|
|||
]
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
||||
},
|
||||
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
|
||||
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
|
||||
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
|
||||
|
@ -212,7 +215,7 @@ TEMPLATES = [
|
|||
"{{cookiecutter.project_slug}}.users.context_processors.allauth_settings",
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#form-renderer
|
||||
|
@ -276,7 +279,7 @@ LOGGING = {
|
|||
"level": "DEBUG",
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "verbose",
|
||||
}
|
||||
},
|
||||
},
|
||||
"root": {"level": "INFO", "handlers": ["console"]},
|
||||
}
|
||||
|
@ -386,7 +389,7 @@ WEBPACK_LOADER = {
|
|||
"STATS_FILE": BASE_DIR / "webpack-stats.json",
|
||||
"POLL_INTERVAL": 0.1,
|
||||
"IGNORE": [r".+\.hot-update.js", r".+\.map"],
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
{%- endif %}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
from .base import * # noqa
|
||||
# ruff: noqa: E501
|
||||
from .base import * # noqa: F403
|
||||
from .base import INSTALLED_APPS
|
||||
from .base import MIDDLEWARE
|
||||
{%- if cookiecutter.frontend_pipeline == 'Webpack' %}
|
||||
from .base import WEBPACK_LOADER
|
||||
{%- endif %}
|
||||
from .base import env
|
||||
|
||||
# GENERAL
|
||||
|
@ -11,7 +17,7 @@ SECRET_KEY = env(
|
|||
default="!!!SET DJANGO_SECRET_KEY!!!",
|
||||
)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
||||
ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1"]
|
||||
ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1"] # noqa: S104
|
||||
|
||||
# CACHES
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -20,7 +26,7 @@ CACHES = {
|
|||
"default": {
|
||||
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
||||
"LOCATION": "",
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
# EMAIL
|
||||
|
@ -37,7 +43,9 @@ EMAIL_HOST = "localhost"
|
|||
EMAIL_PORT = 1025
|
||||
{%- else -%}
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
|
||||
EMAIL_BACKEND = env("DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend")
|
||||
EMAIL_BACKEND = env(
|
||||
"DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend",
|
||||
)
|
||||
{%- endif %}
|
||||
|
||||
{%- if cookiecutter.use_whitenoise == 'y' %}
|
||||
|
@ -45,7 +53,7 @@ EMAIL_BACKEND = env("DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.c
|
|||
# WhiteNoise
|
||||
# ------------------------------------------------------------------------------
|
||||
# http://whitenoise.evans.io/en/latest/django.html#using-whitenoise-in-development
|
||||
INSTALLED_APPS = ["whitenoise.runserver_nostatic"] + INSTALLED_APPS # noqa: F405
|
||||
INSTALLED_APPS = ["whitenoise.runserver_nostatic", *INSTALLED_APPS]
|
||||
{% endif %}
|
||||
|
||||
# # django-debug-toolbar
|
||||
|
@ -80,7 +88,7 @@ INSTALLED_APPS = ["whitenoise.runserver_nostatic"] + INSTALLED_APPS # noqa: F40
|
|||
# django-extensions
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration
|
||||
INSTALLED_APPS += ["django_extensions"] # noqa: F405
|
||||
INSTALLED_APPS += ["django_extensions"]
|
||||
{% if cookiecutter.use_celery == 'y' -%}
|
||||
|
||||
# Celery
|
||||
|
@ -96,7 +104,7 @@ CELERY_TASK_EAGER_PROPAGATES = True
|
|||
{%- if cookiecutter.frontend_pipeline == 'Webpack' %}
|
||||
# django-webpack-loader
|
||||
# ------------------------------------------------------------------------------
|
||||
WEBPACK_LOADER["DEFAULT"]["CACHE"] = not DEBUG # noqa: F405
|
||||
WEBPACK_LOADER["DEFAULT"]["CACHE"] = not DEBUG
|
||||
|
||||
{%- endif %}
|
||||
# Your stuff...
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# ruff: noqa: E501
|
||||
{% if cookiecutter.use_sentry == 'y' -%}
|
||||
import logging
|
||||
|
||||
|
@ -12,7 +13,12 @@ from sentry_sdk.integrations.logging import LoggingIntegration
|
|||
from sentry_sdk.integrations.redis import RedisIntegration
|
||||
|
||||
{% endif -%}
|
||||
from .base import * # noqa
|
||||
from .base import * # noqa: F403
|
||||
from .base import DATABASES
|
||||
from .base import INSTALLED_APPS
|
||||
{%- if cookiecutter.use_drf == "y" %}
|
||||
from .base import SPECTACULAR_SETTINGS
|
||||
{%- endif %}
|
||||
from .base import env
|
||||
|
||||
# GENERAL
|
||||
|
@ -24,7 +30,7 @@ ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["{{ cookiecutter.domai
|
|||
|
||||
# DATABASES
|
||||
# ------------------------------------------------------------------------------
|
||||
DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60) # noqa: F405
|
||||
DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60)
|
||||
|
||||
# CACHES
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -38,7 +44,7 @@ CACHES = {
|
|||
# https://github.com/jazzband/django-redis#memcached-exceptions-behavior
|
||||
"IGNORE_EXCEPTIONS": True,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
# SECURITY
|
||||
|
@ -56,17 +62,23 @@ CSRF_COOKIE_SECURE = True
|
|||
# TODO: set this to 60 seconds first and then to 518400 once you prove the former works
|
||||
SECURE_HSTS_SECONDS = 60
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-include-subdomains
|
||||
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool("DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True)
|
||||
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool(
|
||||
"DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS",
|
||||
default=True,
|
||||
)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-preload
|
||||
SECURE_HSTS_PRELOAD = env.bool("DJANGO_SECURE_HSTS_PRELOAD", default=True)
|
||||
# https://docs.djangoproject.com/en/dev/ref/middleware/#x-content-type-options-nosniff
|
||||
SECURE_CONTENT_TYPE_NOSNIFF = env.bool("DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True)
|
||||
SECURE_CONTENT_TYPE_NOSNIFF = env.bool(
|
||||
"DJANGO_SECURE_CONTENT_TYPE_NOSNIFF",
|
||||
default=True,
|
||||
)
|
||||
|
||||
{% if cookiecutter.cloud_provider != 'None' -%}
|
||||
# STORAGES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://django-storages.readthedocs.io/en/latest/#installation
|
||||
INSTALLED_APPS += ["storages"] # noqa: F405
|
||||
INSTALLED_APPS += ["storages"]
|
||||
{%- endif -%}
|
||||
{% if cookiecutter.cloud_provider == 'AWS' %}
|
||||
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
|
||||
|
@ -103,35 +115,75 @@ AZURE_CONTAINER = env("DJANGO_AZURE_CONTAINER_NAME")
|
|||
{% endif -%}
|
||||
|
||||
{% if cookiecutter.cloud_provider != 'None' or cookiecutter.use_whitenoise == 'y' -%}
|
||||
# STATIC
|
||||
# STATIC & MEDIA
|
||||
# ------------------------
|
||||
{% endif -%}
|
||||
{% if cookiecutter.use_whitenoise == 'y' -%}
|
||||
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
|
||||
{% elif cookiecutter.cloud_provider == 'AWS' -%}
|
||||
STATICFILES_STORAGE = "{{cookiecutter.project_slug}}.utils.storages.StaticS3Storage"
|
||||
STORAGES = {
|
||||
{%- if cookiecutter.use_whitenoise == 'y' %}
|
||||
"default": {
|
||||
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||
},
|
||||
"staticfiles": {
|
||||
"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
|
||||
},
|
||||
{%- elif cookiecutter.cloud_provider == 'AWS' %}
|
||||
"default": {
|
||||
"BACKEND": "storages.backends.s3.S3Storage",
|
||||
"OPTIONS": {
|
||||
"location": "media",
|
||||
"file_overwrite": False,
|
||||
},
|
||||
},
|
||||
"staticfiles": {
|
||||
"BACKEND": "storages.backends.s3.S3Storage",
|
||||
"OPTIONS": {
|
||||
"location": "static",
|
||||
"default_acl": "public-read",
|
||||
},
|
||||
},
|
||||
{%- elif cookiecutter.cloud_provider == 'GCP' %}
|
||||
"default": {
|
||||
"BACKEND": "storages.backends.gcloud.GoogleCloudStorage",
|
||||
"OPTIONS": {
|
||||
"location": "media",
|
||||
"file_overwrite": False,
|
||||
},
|
||||
},
|
||||
"staticfiles": {
|
||||
"BACKEND": "storages.backends.gcloud.GoogleCloudStorage",
|
||||
"OPTIONS": {
|
||||
"location": "static",
|
||||
"default_acl": "publicRead",
|
||||
},
|
||||
},
|
||||
{%- elif cookiecutter.cloud_provider == 'Azure' %}
|
||||
"default": {
|
||||
"BACKEND": "storages.backends.azure_storage.AzureStorage",
|
||||
"OPTIONS": {
|
||||
"location": "media",
|
||||
"file_overwrite": False,
|
||||
},
|
||||
},
|
||||
"staticfiles": {
|
||||
"BACKEND": "storages.backends.azure_storage.AzureStorage",
|
||||
"OPTIONS": {
|
||||
"location": "static",
|
||||
},
|
||||
},
|
||||
{%- endif %}
|
||||
}
|
||||
{%- endif %}
|
||||
|
||||
{%- if cookiecutter.cloud_provider == 'AWS' %}
|
||||
MEDIA_URL = f"https://{aws_s3_domain}/media/"
|
||||
COLLECTFAST_STRATEGY = "collectfast.strategies.boto3.Boto3Strategy"
|
||||
STATIC_URL = f"https://{aws_s3_domain}/static/"
|
||||
{% elif cookiecutter.cloud_provider == 'GCP' -%}
|
||||
STATICFILES_STORAGE = "{{cookiecutter.project_slug}}.utils.storages.StaticGoogleCloudStorage"
|
||||
{%- elif cookiecutter.cloud_provider == 'GCP' %}
|
||||
MEDIA_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/"
|
||||
COLLECTFAST_STRATEGY = "collectfast.strategies.gcloud.GoogleCloudStrategy"
|
||||
STATIC_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/static/"
|
||||
{% elif cookiecutter.cloud_provider == 'Azure' -%}
|
||||
STATICFILES_STORAGE = "{{cookiecutter.project_slug}}.utils.storages.StaticAzureStorage"
|
||||
STATIC_URL = f"https://{AZURE_ACCOUNT_NAME}.blob.core.windows.net/static/"
|
||||
{% endif -%}
|
||||
|
||||
# MEDIA
|
||||
# ------------------------------------------------------------------------------
|
||||
{%- if cookiecutter.cloud_provider == 'AWS' %}
|
||||
DEFAULT_FILE_STORAGE = "{{cookiecutter.project_slug}}.utils.storages.MediaS3Storage"
|
||||
MEDIA_URL = f"https://{aws_s3_domain}/media/"
|
||||
{%- elif cookiecutter.cloud_provider == 'GCP' %}
|
||||
DEFAULT_FILE_STORAGE = "{{cookiecutter.project_slug}}.utils.storages.MediaGoogleCloudStorage"
|
||||
MEDIA_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/"
|
||||
{%- elif cookiecutter.cloud_provider == 'Azure' %}
|
||||
DEFAULT_FILE_STORAGE = "{{cookiecutter.project_slug}}.utils.storages.MediaAzureStorage"
|
||||
MEDIA_URL = f"https://{AZURE_ACCOUNT_NAME}.blob.core.windows.net/media/"
|
||||
STATIC_URL = f"https://{AZURE_ACCOUNT_NAME}.blob.core.windows.net/static/"
|
||||
{%- endif %}
|
||||
|
||||
# EMAIL
|
||||
|
@ -157,7 +209,7 @@ ADMIN_URL = env("DJANGO_ADMIN_URL")
|
|||
# Anymail
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://anymail.readthedocs.io/en/stable/installation/#installing-anymail
|
||||
INSTALLED_APPS += ["anymail"] # noqa: F405
|
||||
INSTALLED_APPS += ["anymail"]
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
|
||||
# https://anymail.readthedocs.io/en/stable/installation/#anymail-settings-reference
|
||||
{%- if cookiecutter.mail_service == 'Mailgun' %}
|
||||
|
@ -230,10 +282,10 @@ COMPRESS_ENABLED = env.bool("COMPRESS_ENABLED", default=True)
|
|||
COMPRESS_STORAGE = "compressor.storage.GzipCompressorFileStorage"
|
||||
{%- elif cookiecutter.cloud_provider in ('AWS', 'GCP', 'Azure') and cookiecutter.use_whitenoise == 'n' %}
|
||||
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_STORAGE
|
||||
COMPRESS_STORAGE = STATICFILES_STORAGE
|
||||
COMPRESS_STORAGE = STORAGES["staticfiles"]["BACKEND"]
|
||||
{%- endif %}
|
||||
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_URL
|
||||
COMPRESS_URL = STATIC_URL{% if cookiecutter.use_whitenoise == 'y' or cookiecutter.cloud_provider == 'None' %} # noqa: F405{% endif %}
|
||||
COMPRESS_URL = STATIC_URL{% if cookiecutter.use_whitenoise == 'y' or cookiecutter.cloud_provider == 'None' %}{% endif %}
|
||||
{%- if cookiecutter.use_whitenoise == 'y' %}
|
||||
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_OFFLINE
|
||||
COMPRESS_OFFLINE = True # Offline compression is required when using Whitenoise
|
||||
|
@ -251,7 +303,7 @@ COMPRESS_FILTERS = {
|
|||
# Collectfast
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://github.com/antonagestam/collectfast#installation
|
||||
INSTALLED_APPS = ["collectfast"] + INSTALLED_APPS # noqa: F405
|
||||
INSTALLED_APPS = ["collectfast", *INSTALLED_APPS]
|
||||
{% endif %}
|
||||
# LOGGING
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -311,7 +363,7 @@ LOGGING = {
|
|||
"level": "DEBUG",
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "verbose",
|
||||
}
|
||||
},
|
||||
},
|
||||
"root": {"level": "INFO", "handlers": ["console"]},
|
||||
"loggers": {
|
||||
|
@ -363,7 +415,7 @@ sentry_sdk.init(
|
|||
# django-rest-framework
|
||||
# -------------------------------------------------------------------------------
|
||||
# Tools that generate code samples can use SERVERS to point to the correct domain
|
||||
SPECTACULAR_SETTINGS["SERVERS"] = [ # noqa: F405
|
||||
SPECTACULAR_SETTINGS["SERVERS"] = [
|
||||
{"url": "https://{{ cookiecutter.domain_name }}", "description": "Production server"},
|
||||
]
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
With these settings, tests run faster.
|
||||
"""
|
||||
|
||||
from .base import * # noqa
|
||||
from .base import * # noqa: F403
|
||||
from .base import TEMPLATES
|
||||
from .base import env
|
||||
|
||||
# GENERAL
|
||||
|
@ -27,7 +28,7 @@ EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
|
|||
|
||||
# DEBUGGING FOR TEMPLATES
|
||||
# ------------------------------------------------------------------------------
|
||||
TEMPLATES[0]["OPTIONS"]["debug"] = True # type: ignore # noqa: F405
|
||||
TEMPLATES[0]["OPTIONS"]["debug"] = True # type: ignore[index]
|
||||
|
||||
# MEDIA
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -37,7 +38,7 @@ MEDIA_URL = "http://media.testserver"
|
|||
{%- if cookiecutter.frontend_pipeline == 'Webpack' %}
|
||||
# django-webpack-loader
|
||||
# ------------------------------------------------------------------------------
|
||||
WEBPACK_LOADER["DEFAULT"]["LOADER_CLASS"] = "webpack_loader.loader.FakeWebpackLoader" # noqa: F405
|
||||
WEBPACK_LOADER["DEFAULT"]["LOADER_CLASS"] = "webpack_loader.loaders.FakeWebpackLoader" # noqa: F405
|
||||
|
||||
{%- endif %}
|
||||
# Your stuff...
|
||||
|
|
|
@ -1,27 +1,37 @@
|
|||
# ruff: noqa
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
from django.contrib import admin
|
||||
{%- if cookiecutter.use_async == 'y' %}
|
||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||
{%- endif %}
|
||||
from django.urls import include, path
|
||||
from django.urls import include
|
||||
from django.urls import path
|
||||
from django.views import defaults as default_views
|
||||
from django.views.generic import TemplateView
|
||||
{%- if cookiecutter.use_drf == 'y' %}
|
||||
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
|
||||
from drf_spectacular.views import SpectacularAPIView
|
||||
from drf_spectacular.views import SpectacularSwaggerView
|
||||
from rest_framework.authtoken.views import obtain_auth_token
|
||||
{%- endif %}
|
||||
|
||||
urlpatterns = [
|
||||
path("", TemplateView.as_view(template_name="pages/home.html"), name="home"),
|
||||
path("about/", TemplateView.as_view(template_name="pages/about.html"), name="about"),
|
||||
path(
|
||||
"about/",
|
||||
TemplateView.as_view(template_name="pages/about.html"),
|
||||
name="about",
|
||||
),
|
||||
# Django Admin, use {% raw %}{% url 'admin:index' %}{% endraw %}
|
||||
path(settings.ADMIN_URL, admin.site.urls),
|
||||
# User management
|
||||
path("users/", include("{{ cookiecutter.project_slug }}.users.urls", namespace="users")),
|
||||
path("accounts/", include("allauth.urls")),
|
||||
# Your stuff: custom urls includes go here
|
||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
# ...
|
||||
# Media files
|
||||
*static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT),
|
||||
]
|
||||
{%- if cookiecutter.use_async == 'y' %}
|
||||
if settings.DEBUG:
|
||||
# Static file serving when using Gunicorn + Uvicorn for local web socket development
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# ruff: noqa
|
||||
"""
|
||||
WSGI config for {{ cookiecutter.project_name }} project.
|
||||
|
||||
|
@ -13,6 +14,7 @@ middleware here, or combine a Django application with an application of another
|
|||
framework.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
|
18
{{cookiecutter.project_slug}}/docs.yml
Normal file
18
{{cookiecutter.project_slug}}/docs.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
version: '3'
|
||||
|
||||
services:
|
||||
docs:
|
||||
image: {{ cookiecutter.project_slug }}_local_docs
|
||||
container_name: {{ cookiecutter.project_slug }}_local_docs
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./compose/local/docs/Dockerfile
|
||||
env_file:
|
||||
- ./.envs/.local/.django
|
||||
volumes:
|
||||
- ./docs:/docs:z
|
||||
- ./config:/app/config:z
|
||||
- ./{{ cookiecutter.project_slug }}:/app/{{ cookiecutter.project_slug }}:z
|
||||
ports:
|
||||
- '9000:9000'
|
||||
command: /start-docs
|
|
@ -1,3 +1,4 @@
|
|||
# ruff: noqa
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
|
|
|
@ -40,25 +40,10 @@ services:
|
|||
env_file:
|
||||
- ./.envs/.local/.postgres
|
||||
|
||||
docs:
|
||||
image: {{ cookiecutter.project_slug }}_local_docs
|
||||
container_name: {{ cookiecutter.project_slug }}_local_docs
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./compose/local/docs/Dockerfile
|
||||
env_file:
|
||||
- ./.envs/.local/.django
|
||||
volumes:
|
||||
- ./docs:/docs:z
|
||||
- ./config:/app/config:z
|
||||
- ./{{ cookiecutter.project_slug }}:/app/{{ cookiecutter.project_slug }}:z
|
||||
ports:
|
||||
- '9000:9000'
|
||||
command: /start-docs
|
||||
{%- if cookiecutter.use_mailpit == 'y' %}
|
||||
|
||||
mailpit:
|
||||
image: axllent/mailpit:latest
|
||||
image: docker.io/axllent/mailpit:latest
|
||||
container_name: {{ cookiecutter.project_slug }}_local_mailpit
|
||||
ports:
|
||||
- "8025:8025"
|
||||
|
@ -67,7 +52,7 @@ services:
|
|||
{%- if cookiecutter.use_celery == 'y' %}
|
||||
|
||||
redis:
|
||||
image: redis:6
|
||||
image: docker.io/redis:6
|
||||
container_name: {{ cookiecutter.project_slug }}_local_redis
|
||||
|
||||
celeryworker:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
# ruff: noqa
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
@ -13,7 +14,7 @@ if __name__ == "__main__":
|
|||
# issue is really that Django is missing to avoid masking other
|
||||
# exceptions on Python 2.
|
||||
try:
|
||||
import django # noqa
|
||||
import django
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# ruff: noqa
|
||||
import os
|
||||
from collections.abc import Sequence
|
||||
from pathlib import Path
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"gulp": "^4.0.2",
|
||||
"gulp-imagemin": "^7.1.0",
|
||||
"gulp-plumber": "^1.2.1",
|
||||
"gulp-postcss": "^9.0.1",
|
||||
"gulp-postcss": "^10.0.0",
|
||||
"gulp-rename": "^2.0.0",
|
||||
"gulp-sass": "^5.0.0",
|
||||
"gulp-uglify-es": "^3.0.0",
|
||||
|
@ -31,7 +31,7 @@
|
|||
"webpack": "^5.65.0",
|
||||
"webpack-bundle-tracker": "^3.0.1",
|
||||
"webpack-cli": "^5.0.1",
|
||||
"webpack-dev-server": "^4.6.0",
|
||||
"webpack-dev-server": "^5.0.2",
|
||||
"webpack-merge": "^5.8.0"
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
@ -67,7 +67,7 @@ services:
|
|||
{%- endif %}
|
||||
|
||||
redis:
|
||||
image: redis:6
|
||||
image: docker.io/redis:6
|
||||
{%- if cookiecutter.use_celery == 'y' %}
|
||||
|
||||
celeryworker:
|
||||
|
|
|
@ -16,28 +16,9 @@ include = ["{{cookiecutter.project_slug}}/**"]
|
|||
omit = ["*/migrations/*", "*/tests/*"]
|
||||
plugins = ["django_coverage_plugin"]
|
||||
|
||||
|
||||
# ==== black ====
|
||||
[tool.black]
|
||||
line-length = 119
|
||||
target-version = ['py311']
|
||||
|
||||
|
||||
# ==== isort ====
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
line_length = 119
|
||||
known_first_party = [
|
||||
"{{cookiecutter.project_slug}}",
|
||||
"config",
|
||||
]
|
||||
skip = ["venv/"]
|
||||
skip_glob = ["**/migrations/*.py"]
|
||||
|
||||
|
||||
# ==== mypy ====
|
||||
[tool.mypy]
|
||||
python_version = "3.11"
|
||||
python_version = "3.12"
|
||||
check_untyped_defs = true
|
||||
ignore_missing_imports = true
|
||||
warn_unused_ignores = true
|
||||
|
@ -58,40 +39,6 @@ ignore_errors = true
|
|||
[tool.django-stubs]
|
||||
django_settings_module = "config.settings.test"
|
||||
|
||||
|
||||
# ==== PyLint ====
|
||||
[tool.pylint.MASTER]
|
||||
load-plugins = [
|
||||
"pylint_django",
|
||||
{%- if cookiecutter.use_celery == "y" %}
|
||||
"pylint_celery",
|
||||
{%- endif %}
|
||||
]
|
||||
django-settings-module = "config.settings.local"
|
||||
|
||||
[tool.pylint.FORMAT]
|
||||
max-line-length = 119
|
||||
|
||||
[tool.pylint."MESSAGES CONTROL"]
|
||||
disable = [
|
||||
"missing-docstring",
|
||||
"invalid-name",
|
||||
]
|
||||
|
||||
[tool.pylint.DESIGN]
|
||||
max-parents = 13
|
||||
|
||||
[tool.pylint.TYPECHECK]
|
||||
generated-members = [
|
||||
"REQUEST",
|
||||
"acl_users",
|
||||
"aq_parent",
|
||||
"[a-zA-Z]+_set{1,2}",
|
||||
"save",
|
||||
"delete",
|
||||
]
|
||||
|
||||
|
||||
# ==== djLint ====
|
||||
[tool.djlint]
|
||||
blank_line_after_tag = "load,extends,endblock"
|
||||
|
@ -110,3 +57,112 @@ indent_size = 2
|
|||
|
||||
[tool.djlint.js]
|
||||
indent_size = 2
|
||||
|
||||
[tool.ruff]
|
||||
# Exclude a variety of commonly ignored directories.
|
||||
exclude = [
|
||||
".bzr",
|
||||
".direnv",
|
||||
".eggs",
|
||||
".git",
|
||||
".git-rewrite",
|
||||
".hg",
|
||||
".mypy_cache",
|
||||
".nox",
|
||||
".pants.d",
|
||||
".pytype",
|
||||
".ruff_cache",
|
||||
".svn",
|
||||
".tox",
|
||||
".venv",
|
||||
"__pypackages__",
|
||||
"_build",
|
||||
"buck-out",
|
||||
"build",
|
||||
"dist",
|
||||
"node_modules",
|
||||
"venv",
|
||||
"*/migrations/*.py",
|
||||
"staticfiles/*"
|
||||
]
|
||||
# Same as Django: https://github.com/cookiecutter/cookiecutter-django/issues/4792.
|
||||
line-length = 88
|
||||
indent-width = 4
|
||||
target-version = "py312"
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = [
|
||||
"F",
|
||||
"E",
|
||||
"W",
|
||||
"C90",
|
||||
"I",
|
||||
"N",
|
||||
"UP",
|
||||
"YTT",
|
||||
# "ANN", # flake8-annotations: we should support this in the future but 100+ errors atm
|
||||
"ASYNC",
|
||||
"S",
|
||||
"BLE",
|
||||
"FBT",
|
||||
"B",
|
||||
"A",
|
||||
"COM",
|
||||
"C4",
|
||||
"DTZ",
|
||||
"T10",
|
||||
"DJ",
|
||||
"EM",
|
||||
"EXE",
|
||||
"FA",
|
||||
'ISC',
|
||||
"ICN",
|
||||
"G",
|
||||
'INP',
|
||||
'PIE',
|
||||
"T20",
|
||||
'PYI',
|
||||
'PT',
|
||||
"Q",
|
||||
"RSE",
|
||||
"RET",
|
||||
"SLF",
|
||||
"SLOT",
|
||||
"SIM",
|
||||
"TID",
|
||||
"TCH",
|
||||
"INT",
|
||||
# "ARG", # Unused function argument
|
||||
"PTH",
|
||||
"ERA",
|
||||
"PD",
|
||||
"PGH",
|
||||
"PL",
|
||||
"TRY",
|
||||
"FLY",
|
||||
# "NPY",
|
||||
# "AIR",
|
||||
"PERF",
|
||||
# "FURB",
|
||||
# "LOG",
|
||||
"RUF"
|
||||
]
|
||||
ignore = [
|
||||
"S101", # Use of assert detected https://docs.astral.sh/ruff/rules/assert/
|
||||
"RUF012", # Mutable class attributes should be annotated with `typing.ClassVar`
|
||||
"SIM102" # sometimes it's better to nest
|
||||
]
|
||||
# Allow fix for all enabled rules (when `--fix`) is provided.
|
||||
fixable = ["ALL"]
|
||||
unfixable = []
|
||||
# Allow unused variables when underscore-prefixed.
|
||||
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||
|
||||
[tool.ruff.format]
|
||||
quote-style = "double"
|
||||
indent-style = "space"
|
||||
skip-magic-trailing-comma = false
|
||||
line-ending = "auto"
|
||||
|
||||
[tool.ruff.lint.isort]
|
||||
force-single-line = true
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
python-slugify==8.0.1 # https://github.com/un33k/python-slugify
|
||||
python-slugify==8.0.4 # https://github.com/un33k/python-slugify
|
||||
Pillow==10.2.0 # https://github.com/python-pillow/Pillow
|
||||
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
|
||||
{%- if cookiecutter.windows == 'y' and cookiecutter.use_docker == 'n' %}
|
||||
|
@ -11,36 +11,36 @@ argon2-cffi==23.1.0 # https://github.com/hynek/argon2_cffi
|
|||
{%- if cookiecutter.use_whitenoise == 'y' %}
|
||||
whitenoise==6.6.0 # https://github.com/evansd/whitenoise
|
||||
{%- endif %}
|
||||
redis==5.0.1 # https://github.com/redis/redis-py
|
||||
redis==5.0.3 # https://github.com/redis/redis-py
|
||||
{%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %}
|
||||
hiredis==2.3.2 # https://github.com/redis/hiredis-py
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_celery == "y" %}
|
||||
celery==5.3.6 # 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.6.0 # https://github.com/celery/django-celery-beat
|
||||
{%- if cookiecutter.use_docker == 'y' %}
|
||||
flower==2.0.1 # https://github.com/mher/flower
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_async == 'y' %}
|
||||
uvicorn[standard]==0.26.0 # https://github.com/encode/uvicorn
|
||||
uvicorn[standard]==0.29.0 # https://github.com/encode/uvicorn
|
||||
{%- endif %}
|
||||
|
||||
# Django
|
||||
# ------------------------------------------------------------------------------
|
||||
django==4.2.9 # pyup: < 5.0 # https://www.djangoproject.com/
|
||||
django==4.2.11 # pyup: < 5.0 # https://www.djangoproject.com/
|
||||
django-environ==0.11.2 # https://github.com/joke2k/django-environ
|
||||
django-model-utils==4.3.1 # https://github.com/jazzband/django-model-utils
|
||||
django-allauth==0.60.1 # https://github.com/pennersr/django-allauth
|
||||
django-model-utils==4.4.0 # https://github.com/jazzband/django-model-utils
|
||||
django-allauth[mfa]==0.61.1 # https://github.com/pennersr/django-allauth
|
||||
django-crispy-forms==2.1 # https://github.com/django-crispy-forms/django-crispy-forms
|
||||
crispy-bootstrap5==2023.10 # https://github.com/django-crispy-forms/crispy-bootstrap5
|
||||
crispy-bootstrap5==2024.2 # https://github.com/django-crispy-forms/crispy-bootstrap5
|
||||
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
|
||||
django-compressor==4.4 # https://github.com/django-compressor/django-compressor
|
||||
{%- endif %}
|
||||
django-redis==5.4.0 # https://github.com/jazzband/django-redis
|
||||
{%- if cookiecutter.use_drf == 'y' %}
|
||||
# Django REST Framework
|
||||
djangorestframework==3.14.0 # https://github.com/encode/django-rest-framework
|
||||
djangorestframework==3.15.0 # https://github.com/encode/django-rest-framework
|
||||
django-cors-headers==4.3.1 # https://github.com/adamchainz/django-cors-headers
|
||||
# DRF-spectacular for api documentation
|
||||
drf-spectacular==0.27.1 # https://github.com/tfranzel/drf-spectacular
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
-r base.txt
|
||||
-r production.txt
|
||||
|
||||
Werkzeug[watchdog]==3.0.1 # https://github.com/pallets/werkzeug
|
||||
ipdb==0.13.13 # https://github.com/gotcha/ipdb
|
||||
{%- if cookiecutter.use_docker == 'y' %}
|
||||
psycopg[c]==3.1.17 # https://github.com/psycopg/psycopg
|
||||
psycopg[c]==3.1.18 # https://github.com/psycopg/psycopg
|
||||
{%- else %}
|
||||
psycopg[binary]==3.1.17 # https://github.com/psycopg/psycopg
|
||||
psycopg[binary]==3.1.18 # https://github.com/psycopg/psycopg
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_async == 'y' or cookiecutter.use_celery == 'y' %}
|
||||
watchfiles==0.21.0 # https://github.com/samuelcolvin/watchfiles
|
||||
|
@ -15,8 +15,8 @@ watchfiles==0.21.0 # https://github.com/samuelcolvin/watchfiles
|
|||
# ------------------------------------------------------------------------------
|
||||
mypy==1.7.1 # https://github.com/python/mypy
|
||||
django-stubs[compatible-mypy]==4.2.7 # https://github.com/typeddjango/django-stubs
|
||||
pytest==7.4.4 # https://github.com/pytest-dev/pytest
|
||||
pytest-sugar==0.9.7 # https://github.com/Frozenball/pytest-sugar
|
||||
pytest==8.1.1 # https://github.com/pytest-dev/pytest
|
||||
pytest-sugar==1.0.0 # https://github.com/Frozenball/pytest-sugar
|
||||
{%- if cookiecutter.use_drf == "y" %}
|
||||
djangorestframework-stubs[compatible-mypy]==3.14.5 # https://github.com/typeddjango/djangorestframework-stubs
|
||||
{%- endif %}
|
||||
|
@ -24,27 +24,21 @@ djangorestframework-stubs[compatible-mypy]==3.14.5 # https://github.com/typeddj
|
|||
# Documentation
|
||||
# ------------------------------------------------------------------------------
|
||||
sphinx==7.2.6 # https://github.com/sphinx-doc/sphinx
|
||||
sphinx-autobuild==2021.3.14 # https://github.com/GaretJax/sphinx-autobuild
|
||||
sphinx-rtd-theme==1.3.0 # https://pypi.org/project/sphinx-rtd-theme/
|
||||
sphinx-autobuild==2024.2.4 # https://github.com/GaretJax/sphinx-autobuild
|
||||
sphinx-rtd-theme==2.0.0 # https://pypi.org/project/sphinx-rtd-theme/
|
||||
|
||||
# Code quality
|
||||
# ------------------------------------------------------------------------------
|
||||
flake8==7.0.0 # https://github.com/PyCQA/flake8
|
||||
flake8-isort==6.1.1 # https://github.com/gforcada/flake8-isort
|
||||
coverage==7.4.0 # https://github.com/nedbat/coveragepy
|
||||
black==23.12.1 # https://github.com/psf/black
|
||||
ruff==0.3.3 # https://github.com/astral-sh/ruff
|
||||
coverage==7.4.4 # https://github.com/nedbat/coveragepy
|
||||
djlint==1.34.1 # https://github.com/Riverside-Healthcare/djLint
|
||||
pylint-django==2.5.5 # https://github.com/PyCQA/pylint-django
|
||||
{%- if cookiecutter.use_celery == 'y' %}
|
||||
pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery
|
||||
{%- endif %}
|
||||
pre-commit==3.6.0 # https://github.com/pre-commit/pre-commit
|
||||
pre-commit==3.6.2 # https://github.com/pre-commit/pre-commit
|
||||
|
||||
# Django
|
||||
# ------------------------------------------------------------------------------
|
||||
factory-boy==3.3.0 # https://github.com/FactoryBoy/factory_boy
|
||||
|
||||
django-debug-toolbar==4.2.0 # https://github.com/jazzband/django-debug-toolbar
|
||||
django-debug-toolbar==4.3.0 # https://github.com/jazzband/django-debug-toolbar
|
||||
django-extensions==3.2.3 # https://github.com/django-extensions/django-extensions
|
||||
django-coverage-plugin==3.1.0 # https://github.com/nedbat/django_coverage_plugin
|
||||
pytest-django==4.7.0 # https://github.com/pytest-dev/pytest-django
|
||||
pytest-django==4.8.0 # https://github.com/pytest-dev/pytest-django
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
-r base.txt
|
||||
|
||||
gunicorn==21.2.0 # https://github.com/benoitc/gunicorn
|
||||
psycopg[c]==3.1.17 # https://github.com/psycopg/psycopg
|
||||
psycopg[c]==3.1.18 # https://github.com/psycopg/psycopg
|
||||
{%- if cookiecutter.use_whitenoise == 'n' %}
|
||||
Collectfast==2.2.0 # https://github.com/antonagestam/collectfast
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_sentry == "y" %}
|
||||
sentry-sdk==1.39.2 # https://github.com/getsentry/sentry-python
|
||||
sentry-sdk==1.43.0 # https://github.com/getsentry/sentry-python
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_docker == "n" and cookiecutter.windows == "y" %}
|
||||
hiredis==2.3.2 # https://github.com/redis/hiredis-py
|
||||
|
@ -24,21 +24,21 @@ django-storages[google]==1.14.2 # https://github.com/jschneier/django-storages
|
|||
django-storages[azure]==1.14.2 # https://github.com/jschneier/django-storages
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.mail_service == 'Mailgun' %}
|
||||
django-anymail[mailgun]==10.2 # https://github.com/anymail/django-anymail
|
||||
django-anymail[mailgun]==10.3 # https://github.com/anymail/django-anymail
|
||||
{%- elif cookiecutter.mail_service == 'Amazon SES' %}
|
||||
django-anymail[amazon-ses]==10.2 # https://github.com/anymail/django-anymail
|
||||
django-anymail[amazon-ses]==10.3 # https://github.com/anymail/django-anymail
|
||||
{%- elif cookiecutter.mail_service == 'Mailjet' %}
|
||||
django-anymail[mailjet]==10.2 # https://github.com/anymail/django-anymail
|
||||
django-anymail[mailjet]==10.3 # https://github.com/anymail/django-anymail
|
||||
{%- elif cookiecutter.mail_service == 'Mandrill' %}
|
||||
django-anymail[mandrill]==10.2 # https://github.com/anymail/django-anymail
|
||||
django-anymail[mandrill]==10.3 # https://github.com/anymail/django-anymail
|
||||
{%- elif cookiecutter.mail_service == 'Postmark' %}
|
||||
django-anymail[postmark]==10.2 # https://github.com/anymail/django-anymail
|
||||
django-anymail[postmark]==10.3 # https://github.com/anymail/django-anymail
|
||||
{%- elif cookiecutter.mail_service == 'Sendgrid' %}
|
||||
django-anymail[sendgrid]==10.2 # https://github.com/anymail/django-anymail
|
||||
django-anymail[sendgrid]==10.3 # https://github.com/anymail/django-anymail
|
||||
{%- elif cookiecutter.mail_service == 'SendinBlue' %}
|
||||
django-anymail[sendinblue]==10.2 # https://github.com/anymail/django-anymail
|
||||
django-anymail[sendinblue]==10.3 # https://github.com/anymail/django-anymail
|
||||
{%- elif cookiecutter.mail_service == 'SparkPost' %}
|
||||
django-anymail[sparkpost]==10.2 # https://github.com/anymail/django-anymail
|
||||
django-anymail[sparkpost]==10.3 # https://github.com/anymail/django-anymail
|
||||
{%- elif cookiecutter.mail_service == 'Other SMTP' %}
|
||||
django-anymail==10.2 # https://github.com/anymail/django-anymail
|
||||
django-anymail==10.3 # https://github.com/anymail/django-anymail
|
||||
{%- endif %}
|
||||
|
|
|
@ -1 +1 @@
|
|||
python-3.11.7
|
||||
python-3.12.2
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
# flake8 and pycodestyle don't support pyproject.toml
|
||||
# https://github.com/PyCQA/flake8/issues/234
|
||||
# https://github.com/PyCQA/pycodestyle/issues/813
|
||||
[flake8]
|
||||
max-line-length = 119
|
||||
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules,venv,.venv
|
||||
extend-ignore = E203
|
||||
|
||||
[pycodestyle]
|
||||
max-line-length = 119
|
||||
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules,venv,.venv
|
|
@ -6,12 +6,22 @@ module.exports = merge(commonConfig, {
|
|||
devtool: 'inline-source-map',
|
||||
devServer: {
|
||||
port: 3000,
|
||||
proxy: {
|
||||
{%- if cookiecutter.use_docker == 'n' %}
|
||||
'/': 'http://0.0.0.0:8000',
|
||||
{%- else %}
|
||||
'/': 'http://django:8000',
|
||||
{%- endif %}
|
||||
proxy: [
|
||||
{
|
||||
context: ['/'],
|
||||
{%- if cookiecutter.use_docker == 'n' %}
|
||||
target: 'http://0.0.0.0:8000',
|
||||
{%- else %}
|
||||
target: 'http://django:8000',
|
||||
{%- endif %}
|
||||
},
|
||||
],
|
||||
client: {
|
||||
overlay: {
|
||||
errors: true,
|
||||
warnings: false,
|
||||
runtimeErrors: true,
|
||||
},
|
||||
},
|
||||
// We need hot=false (Disable HMR) to set liveReload=true
|
||||
hot: false,
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
__version__ = "{{ cookiecutter.version }}"
|
||||
__version_info__ = tuple(int(num) if num.isdigit() else num for num in __version__.replace("-", ".", 1).split("."))
|
||||
__version_info__ = tuple(
|
||||
int(num) if num.isdigit() else num
|
||||
for num in __version__.replace("-", ".", 1).split(".")
|
||||
)
|
||||
|
|
|
@ -5,10 +5,10 @@ from {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory
|
|||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def media_storage(settings, tmpdir):
|
||||
def _media_storage(settings, tmpdir) -> None:
|
||||
settings.MEDIA_ROOT = tmpdir.strpath
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@pytest.fixture()
|
||||
def user(db) -> User:
|
||||
return UserFactory()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import django.contrib.sites.models
|
||||
from django.contrib.sites.models import _simple_domain_name_validator
|
||||
from django.db import migrations, models
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
@ -38,5 +39,5 @@ class Migration(migrations.Migration):
|
|||
},
|
||||
bases=(models.Model,),
|
||||
managers=[("objects", django.contrib.sites.models.SiteManager())],
|
||||
)
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import django.contrib.sites.models
|
||||
from django.db import migrations, models
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -23,7 +23,7 @@ def _update_or_create_site_with_sequence(site_model, connection, domain, name):
|
|||
# site is created.
|
||||
# To avoid this, we need to manually update DB sequence and make sure it's
|
||||
# greater than the maximum value.
|
||||
max_id = site_model.objects.order_by('-id').first().id
|
||||
max_id = site_model.objects.order_by("-id").first().id
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("SELECT last_value from django_site_id_seq")
|
||||
(current_id,) = cursor.fetchone()
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Account Inactive" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Account Inactive" %}</h1>
|
||||
<p>{% translate "This account is inactive." %}</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,14 +0,0 @@
|
|||
{% raw %}{% extends "base.html" %}
|
||||
|
||||
{% block title %}
|
||||
{% block head_title %}
|
||||
{% endblock head_title %}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-6 offset-md-3">
|
||||
{% block inner %}{% endblock inner %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
{%- endraw %}
|
|
@ -0,0 +1,11 @@
|
|||
{% raw %}{% extends "account/base_manage.html" %}
|
||||
|
||||
{% block main %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock main %}{% endraw %}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
{% raw %}
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Account" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "E-mail Addresses" %}</h1>
|
||||
{% if user.emailaddress_set.all %}
|
||||
<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 %}
|
||||
<fieldset class="blockLabels">
|
||||
{% for emailaddress in user.emailaddress_set.all %}
|
||||
<div class="radio">
|
||||
<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 }}" />
|
||||
{{ emailaddress.email }}
|
||||
{% if emailaddress.verified %}
|
||||
<span class="verified">{% translate "Verified" %}</span>
|
||||
{% else %}
|
||||
<span class="unverified">{% translate "Unverified" %}</span>
|
||||
{% endif %}
|
||||
{% if emailaddress.primary %}
|
||||
<span class="primary">{% translate "Primary" %}</span>
|
||||
{% endif %}
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="form-group">
|
||||
<button class="secondaryAction btn btn-primary"
|
||||
type="submit"
|
||||
name="action_primary">{% translate "Make Primary" %}</button>
|
||||
<button class="secondaryAction btn btn-primary"
|
||||
type="submit"
|
||||
name="action_send">{% translate "Re-send Verification" %}</button>
|
||||
<button class="primaryAction btn btn-primary"
|
||||
type="submit"
|
||||
name="action_remove">{% translate "Remove" %}</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% 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>
|
||||
<form method="post" action="{% url 'account_email' %}" class="add_email">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button class="btn btn-primary" name="action_add" type="submit">{% translate "Add E-mail" %}</button>
|
||||
</form>
|
||||
{% endblock inner %}
|
||||
{% block inline_javascript %}
|
||||
{{ block.super }}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
const message = "{% translate 'Do you really want to remove the selected e-mail address?' %}";
|
||||
const actions = document.getElementsByName('action_remove');
|
||||
if (actions.length) {
|
||||
actions[0].addEventListener("click", function(e) {
|
||||
if (!confirm(message)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
Array.from(document.getElementsByClassName('form-group')).forEach(x => x.classList.remove('row'));
|
||||
});
|
||||
</script>
|
||||
{% endblock inline_javascript %}
|
||||
{%- endraw %}
|
|
@ -1,28 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load account %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Confirm E-mail Address" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Confirm E-mail Address" %}</h1>
|
||||
{% if confirmation %}
|
||||
{% user_display confirmation.email_address.user as user_display %}
|
||||
<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 %}">
|
||||
{% csrf_token %}
|
||||
<button class="btn btn-primary" type="submit">{% translate "Confirm" %}</button>
|
||||
</form>
|
||||
{% else %}
|
||||
{% url 'account_email' as email_url %}
|
||||
<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>
|
||||
{% endif %}
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,53 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load account socialaccount %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Sign In" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Sign In" %}</h1>
|
||||
{% get_providers as socialaccount_providers %}
|
||||
{% if socialaccount_providers %}
|
||||
<p>
|
||||
{% translate "Please sign in with one of your existing third party accounts:" %}
|
||||
{% if ACCOUNT_ALLOW_REGISTRATION %}
|
||||
{% blocktranslate trimmed %}
|
||||
Or, <a href="{{ signup_url }}">sign up</a>
|
||||
for a {{ site_name }} account and sign in below:
|
||||
{% endblocktranslate %}
|
||||
{% endif %}
|
||||
</p>
|
||||
<div class="socialaccount_ballot">
|
||||
<ul class="socialaccount_providers">
|
||||
{% include "socialaccount/snippets/provider_list.html" with process="login" %}
|
||||
</ul>
|
||||
<div class="login-or">{% translate "or" %}</div>
|
||||
</div>
|
||||
{% include "socialaccount/snippets/login_extra.html" %}
|
||||
{% else %}
|
||||
{% if ACCOUNT_ALLOW_REGISTRATION %}
|
||||
<p>
|
||||
{% blocktranslate trimmed %}
|
||||
If you have not created an account yet, then please
|
||||
<a href="{{ signup_url }}">sign up</a> first.
|
||||
{% endblocktranslate %}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<form class="login" method="post" action="{% url 'account_login' %}">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
{% if redirect_field_value %}
|
||||
<input type="hidden"
|
||||
name="{{ redirect_field_name }}"
|
||||
value="{{ redirect_field_value }}" />
|
||||
{% endif %}
|
||||
<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>
|
||||
</form>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,21 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Sign Out" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Sign Out" %}</h1>
|
||||
<p>{% translate "Are you sure you want to sign out?" %}</p>
|
||||
<form method="post" action="{% url 'account_logout' %}">
|
||||
{% csrf_token %}
|
||||
{% if redirect_field_value %}
|
||||
<input type="hidden"
|
||||
name="{{ redirect_field_name }}"
|
||||
value="{{ redirect_field_value }}" />
|
||||
{% endif %}
|
||||
<button class="btn btn-danger" type="submit">{% translate "Sign Out" %}</button>
|
||||
</form>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,19 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Change Password" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Change Password" %}</h1>
|
||||
<form method="post"
|
||||
action="{% url 'account_change_password' %}"
|
||||
class="password_change">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button class="btn btn-primary" type="submit" name="action">{% translate "Change Password" %}</button>
|
||||
</form>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,29 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load account %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Password Reset" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Password Reset" %}</h1>
|
||||
{% if user.is_authenticated %}
|
||||
{% include "account/snippets/already_logged_in.html" %}
|
||||
{% endif %}
|
||||
<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">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<input class="btn btn-primary"
|
||||
type="submit"
|
||||
value="{% translate 'Reset My Password' %}" />
|
||||
</form>
|
||||
<p>{% blocktranslate %}Please contact us if you have any trouble resetting your password.{% endblocktranslate %}</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,18 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load account %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Password Reset" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Password Reset" %}</h1>
|
||||
{% if user.is_authenticated %}
|
||||
{% include "account/snippets/already_logged_in.html" %}
|
||||
{% endif %}
|
||||
<p>
|
||||
{% blocktranslate %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}
|
||||
</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,37 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Change Password" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% if token_fail %}
|
||||
{% translate "Bad Token" %}
|
||||
{% else %}
|
||||
{% translate "Change Password" %}
|
||||
{% endif %}
|
||||
</h1>
|
||||
{% if token_fail %}
|
||||
{% 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>
|
||||
{% else %}
|
||||
{% if form %}
|
||||
<form method="post" action=".">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<input class="btn btn-primary"
|
||||
type="submit"
|
||||
name="action"
|
||||
value="{% translate 'change password' %}" />
|
||||
</form>
|
||||
{% else %}
|
||||
<p>{% translate "Your password is now changed." %}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,12 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Change Password" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Change Password" %}</h1>
|
||||
<p>{% translate "Your password is now changed." %}</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,22 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Set Password" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Set Password" %}</h1>
|
||||
<form method="post"
|
||||
action="{% url 'account_set_password' %}"
|
||||
class="password_set">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<input class="btn btn-primary"
|
||||
type="submit"
|
||||
name="action"
|
||||
value="{% translate 'Set Password' %}" />
|
||||
</form>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,28 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Signup" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Sign Up" %}</h1>
|
||||
<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' %}">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
{% if redirect_field_value %}
|
||||
<input type="hidden"
|
||||
name="{{ redirect_field_name }}"
|
||||
value="{{ redirect_field_value }}" />
|
||||
{% endif %}
|
||||
<button class="btn btn-primary" type="submit">{% translate "Sign Up" %} »</button>
|
||||
</form>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,12 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Sign Up Closed" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Sign Up Closed" %}</h1>
|
||||
<p>{% translate "We are sorry, but the sign up is currently closed." %}</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,14 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Verify Your E-mail Address" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Verify Your E-mail Address" %}</h1>
|
||||
<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 inner %}
|
||||
{%- endraw %}
|
|
@ -1,25 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Verify Your E-mail Address" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Verify Your E-mail Address" %}</h1>
|
||||
{% url 'account_email' as email_url %}
|
||||
<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
|
||||
verify ownership of your e-mail address. {% endblocktranslate %}
|
||||
</p>
|
||||
<p>
|
||||
{% blocktranslate %}We have sent an e-mail to you for
|
||||
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>
|
||||
<p>
|
||||
{% blocktranslate %}<strong>Note:</strong> you can still <a href="{{ email_url }}">change your e-mail address</a>.{% endblocktranslate %}
|
||||
</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -0,0 +1,7 @@
|
|||
{% raw %}{% load i18n %}
|
||||
{% load allauth %}
|
||||
|
||||
<div class="alert alert-error">
|
||||
{% slot message %}
|
||||
{% endslot %}
|
||||
</div>{% endraw %}
|
|
@ -0,0 +1,6 @@
|
|||
{% raw %}{% load allauth %}
|
||||
|
||||
<span class="badge {% if 'success' in attrs.tags %}bg-success{% endif %} {% if 'warning' in attrs.tags %}bg-warning{% endif %} {% if 'secondary' in attrs.tags %}bg-secondary{% endif %} {% if 'danger' in attrs.tags %}bg-danger{% endif %} {% if 'primary' in attrs.tags %}bg-primary{% endif %}">
|
||||
{% slot %}
|
||||
{% endslot %}
|
||||
</span>{% endraw %}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user