Merge branch 'refs/heads/master' into dependabot/npm_and_yarn/{{cookiecutter.project_slug}}/css-loader-7.1.2

This commit is contained in:
Bruno Alla 2024-08-20 11:28:10 +02:00
commit a9801d3eee
No known key found for this signature in database
42 changed files with 855 additions and 273 deletions

2
.github/FUNDING.yml vendored
View File

@ -1,5 +1,5 @@
# These are supported funding model platforms # These are supported funding model platforms
github: [pydanny, browniebroke] github: [pydanny, browniebroke, luzfcb]
patreon: feldroy patreon: feldroy
open_collective: cookiecutter-django open_collective: cookiecutter-django

View File

@ -1578,5 +1578,45 @@
"name": "Nadav Peretz", "name": "Nadav Peretz",
"github_login": "nadavperetz", "github_login": "nadavperetz",
"twitter_username": "" "twitter_username": ""
},
{
"name": "Param Kapur",
"github_login": "paramkpr",
"twitter_username": "ParamKapur"
},
{
"name": "Jason Mok",
"github_login": "jasonmokk",
"twitter_username": ""
},
{
"name": "Manas Mallick",
"github_login": "ManDun",
"twitter_username": ""
},
{
"name": "Alexandr Artemyev",
"github_login": "Mogost",
"twitter_username": "MOGOST"
},
{
"name": "Ali Shamakhi",
"github_login": "ali-shamakhi",
"twitter_username": ""
},
{
"name": "Filipe Nascimento",
"github_login": "FilipeNas",
"twitter_username": ""
},
{
"name": "Kevin Mills",
"github_login": "millsks",
"twitter_username": ""
},
{
"name": "milvagox",
"github_login": "milvagox",
"twitter_username": "milvagox"
} }
] ]

View File

@ -26,14 +26,14 @@ repos:
args: ["--tab-width", "2"] args: ["--tab-width", "2"]
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v3.15.2 rev: v3.17.0
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: [--py312-plus] args: [--py312-plus]
exclude: hooks/ exclude: hooks/
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 24.4.2 rev: 24.8.0
hooks: hooks:
- id: black - id: black
@ -43,7 +43,7 @@ repos:
- id: isort - id: isort
- repo: https://github.com/PyCQA/flake8 - repo: https://github.com/PyCQA/flake8
rev: 7.0.0 rev: 7.1.1
hooks: hooks:
- id: flake8 - id: flake8

View File

@ -3,6 +3,559 @@ All enhancements and patches to Cookiecutter Django will be documented in this f
<!-- GENERATOR_PLACEHOLDER --> <!-- GENERATOR_PLACEHOLDER -->
## 2024.08.19
### Updated
- Update factory-boy to 3.3.1 ([#5307](https://github.com/cookiecutter/cookiecutter-django/pull/5307))
## 2024.08.17
### Updated
- Update ruff to 0.6.1 ([#5303](https://github.com/cookiecutter/cookiecutter-django/pull/5303))
## 2024.08.16
### Updated
- Update django-allauth to 64.1.0 ([#5302](https://github.com/cookiecutter/cookiecutter-django/pull/5302))
## 2024.08.15
### Updated
- Update ruff to 0.6.0 ([#5300](https://github.com/cookiecutter/cookiecutter-django/pull/5300))
## 2024.08.13
### Updated
- Update tox to 4.18.0 ([#5299](https://github.com/cookiecutter/cookiecutter-django/pull/5299))
- Update sentry-sdk to 2.13.0 ([#5298](https://github.com/cookiecutter/cookiecutter-django/pull/5298))
- Update uvicorn to 0.30.6 ([#5295](https://github.com/cookiecutter/cookiecutter-django/pull/5295))
## 2024.08.12
### Updated
- Update gunicorn to 23.0.0 ([#5294](https://github.com/cookiecutter/cookiecutter-django/pull/5294))
## 2024.08.09
### Updated
- Update Ruff pre-commit hook to v0.5.7 ([#5293](https://github.com/cookiecutter/cookiecutter-django/pull/5293))
## 2024.08.08
### Updated
- Update ruff to 0.5.7 ([#5291](https://github.com/cookiecutter/cookiecutter-django/pull/5291))
- Bump python from 3.12.4 to 3.12.5 in docs Docker image ([#5287](https://github.com/cookiecutter/cookiecutter-django/pull/5287))
- Bump python from 3.12.4 to 3.12.5 in local Docker image ([#5289](https://github.com/cookiecutter/cookiecutter-django/pull/5289))
- Bump python from 3.12.4 to 3.12.5 in production Docker image ([#5290](https://github.com/cookiecutter/cookiecutter-django/pull/5290))
## 2024.08.07
### Updated
- Update tox to 4.17.1 ([#5285](https://github.com/cookiecutter/cookiecutter-django/pull/5285))
- Update django-anymail to 11.1 ([#5286](https://github.com/cookiecutter/cookiecutter-django/pull/5286))
## 2024.08.06
### Updated
- Update django to 5.0.8 ([#5281](https://github.com/cookiecutter/cookiecutter-django/pull/5281))
## 2024.08.05
### Documentation
- Simplify documentation for https in local development ([#5252](https://github.com/cookiecutter/cookiecutter-django/pull/5252))
- Add Medium story in the Articles section ([#5275](https://github.com/cookiecutter/cookiecutter-django/pull/5275))
### Updated
- Update coverage to 7.6.1 ([#5276](https://github.com/cookiecutter/cookiecutter-django/pull/5276))
- Auto-update pre-commit hooks ([#5277](https://github.com/cookiecutter/cookiecutter-django/pull/5277))
## 2024.08.04
### Updated
- Update uvicorn to 0.30.5 ([#5272](https://github.com/cookiecutter/cookiecutter-django/pull/5272))
- Update ruff to 0.5.6 ([#5273](https://github.com/cookiecutter/cookiecutter-django/pull/5273))
- Auto-update pre-commit hooks ([#5274](https://github.com/cookiecutter/cookiecutter-django/pull/5274))
## 2024.07.31
### Updated
- Update uvicorn to 0.30.4 ([#5271](https://github.com/cookiecutter/cookiecutter-django/pull/5271))
- Update mypy to 1.11.1 ([#5270](https://github.com/cookiecutter/cookiecutter-django/pull/5270))
- Update pre-commit to 3.8.0 ([#5257](https://github.com/cookiecutter/cookiecutter-django/pull/5257))
- Update pyupgrade pre-commit hook to v3.17.0 ([#5258](https://github.com/cookiecutter/cookiecutter-django/pull/5258))
- Update redis to 5.0.8 ([#5265](https://github.com/cookiecutter/cookiecutter-django/pull/5265))
- Update django-stubs to 5.0.4 ([#5256](https://github.com/cookiecutter/cookiecutter-django/pull/5256))
- Update mypy to 1.11.0 ([#5231](https://github.com/cookiecutter/cookiecutter-django/pull/5231))
- Update django-allauth to 64.0.0 ([#5269](https://github.com/cookiecutter/cookiecutter-django/pull/5269))
- Update sentry-sdk to 2.12.0 ([#5268](https://github.com/cookiecutter/cookiecutter-django/pull/5268))
## 2024.07.26
### Updated
- Update ruff to 0.5.5 ([#5250](https://github.com/cookiecutter/cookiecutter-django/pull/5250))
## 2024.07.25
### Changed
- Upgrade to Django 5.0 ([#5199](https://github.com/cookiecutter/cookiecutter-django/pull/5199))
### Updated
- Update pytest to 8.3.2 ([#5249](https://github.com/cookiecutter/cookiecutter-django/pull/5249))
- Update sentry-sdk to 2.11.0 ([#5247](https://github.com/cookiecutter/cookiecutter-django/pull/5247))
## 2024.07.24
### Changed
- fix non existent of two scoops of django image ([#5248](https://github.com/cookiecutter/cookiecutter-django/pull/5248))
## 2024.07.23
### Changed
- Ensure that awscli service has a CMD to fix #5241 ([#5245](https://github.com/cookiecutter/cookiecutter-django/pull/5245))
### Fixed
- Downgrade watchfiles ([#5243](https://github.com/cookiecutter/cookiecutter-django/pull/5243))
## 2024.07.22
### Updated
- Update django-compressor to 4.5.1 ([#5240](https://github.com/cookiecutter/cookiecutter-django/pull/5240))
## 2024.07.21
### Updated
- Update ruff to 0.5.4 ([#5237](https://github.com/cookiecutter/cookiecutter-django/pull/5237))
- Update pytest to 8.3.1 ([#5236](https://github.com/cookiecutter/cookiecutter-django/pull/5236))
- Update sphinx to 7.4.7 ([#5235](https://github.com/cookiecutter/cookiecutter-django/pull/5235))
## 2024.07.20
### Updated
- Update hiredis to 3.0.0 ([#5228](https://github.com/cookiecutter/cookiecutter-django/pull/5228))
- Update uvicorn to 0.30.3 ([#5234](https://github.com/cookiecutter/cookiecutter-django/pull/5234))
- Update django-crispy-forms to 2.3 ([#5229](https://github.com/cookiecutter/cookiecutter-django/pull/5229))
- Auto-update pre-commit hooks ([#5232](https://github.com/cookiecutter/cookiecutter-django/pull/5232))
## 2024.07.19
### Changed
- Use &#34;ENV key=value&#34; instead of &#34;ENV key value&#34; in Dockerfiles ([#5225](https://github.com/cookiecutter/cookiecutter-django/pull/5225))
### Updated
- Update django-upgrade to 1.20.0 ([#5227](https://github.com/cookiecutter/cookiecutter-django/pull/5227))
- Update ruff to 0.5.3 ([#5224](https://github.com/cookiecutter/cookiecutter-django/pull/5224))
## 2024.07.18
### Updated
- Update sphinx to 7.4.6 ([#5223](https://github.com/cookiecutter/cookiecutter-django/pull/5223))
## 2024.07.17
### Updated
- Update sphinx to 7.4.5 ([#5222](https://github.com/cookiecutter/cookiecutter-django/pull/5222))
## 2024.07.16
### Fixed
- Clear `ENTRYPOINT` in `awscli` image to allow script execution ([#5221](https://github.com/cookiecutter/cookiecutter-django/pull/5221))
### Updated
- Update sphinx to 7.4.4 ([#5218](https://github.com/cookiecutter/cookiecutter-django/pull/5218))
## 2024.07.15
### Updated
- Update sentry-sdk to 2.10.0 ([#5216](https://github.com/cookiecutter/cookiecutter-django/pull/5216))
- Update sphinx to 7.4.2 ([#5215](https://github.com/cookiecutter/cookiecutter-django/pull/5215))
- Update ruff to 0.5.2 ([#5211](https://github.com/cookiecutter/cookiecutter-django/pull/5211))
- Update sphinx to 7.4.0 ([#5214](https://github.com/cookiecutter/cookiecutter-django/pull/5214))
## 2024.07.12
### Updated
- Update django-allauth to 0.63.6 ([#5210](https://github.com/cookiecutter/cookiecutter-django/pull/5210))
- Update django-allauth to 0.63.5 ([#5206](https://github.com/cookiecutter/cookiecutter-django/pull/5206))
- Update coverage to 7.6.0 ([#5207](https://github.com/cookiecutter/cookiecutter-django/pull/5207))
- Update django-anymail to 11.0.1 ([#5208](https://github.com/cookiecutter/cookiecutter-django/pull/5208))
## 2024.07.10
### Updated
- Update django-allauth to 0.63.4 ([#5204](https://github.com/cookiecutter/cookiecutter-django/pull/5204))
- Update django to 4.2.14 ([#5200](https://github.com/cookiecutter/cookiecutter-django/pull/5200))
- Update collectfasta to 3.2.0 ([#5201](https://github.com/cookiecutter/cookiecutter-django/pull/5201))
- Update sentry-sdk to 2.9.0 ([#5202](https://github.com/cookiecutter/cookiecutter-django/pull/5202))
- Update django-debug-toolbar to 4.4.6 ([#5203](https://github.com/cookiecutter/cookiecutter-django/pull/5203))
## 2024.07.09
### Changed
- Migrate from Collectfast to Collestfasta ([#5172](https://github.com/cookiecutter/cookiecutter-django/pull/5172))
### Documentation
- Fix a typo in the `--all` option of the `makemessages` command ([#5198](https://github.com/cookiecutter/cookiecutter-django/pull/5198))
### Updated
- Update django-storages to 1.14.4 ([#5197](https://github.com/cookiecutter/cookiecutter-django/pull/5197))
## 2024.07.08
### Updated
- Update ruff to 0.5.1 ([#5190](https://github.com/cookiecutter/cookiecutter-django/pull/5190))
- Update django-debug-toolbar to 4.4.5 ([#5192](https://github.com/cookiecutter/cookiecutter-django/pull/5192))
- Update sentry-sdk to 2.8.0 ([#5195](https://github.com/cookiecutter/cookiecutter-django/pull/5195))
## 2024.07.05
### Updated
- Update django-debug-toolbar to 4.4.3 ([#5189](https://github.com/cookiecutter/cookiecutter-django/pull/5189))
## 2024.07.02
### Updated
- Update pillow to 10.4.0 ([#5182](https://github.com/cookiecutter/cookiecutter-django/pull/5182))
## 2024.07.01
### Updated
- Update ruff to 0.5.0 ([#5181](https://github.com/cookiecutter/cookiecutter-django/pull/5181))
- Update sentry-sdk to 2.7.1 ([#5174](https://github.com/cookiecutter/cookiecutter-django/pull/5174))
- Auto-update pre-commit hooks ([#5175](https://github.com/cookiecutter/cookiecutter-django/pull/5175))
- Update psycopg to 3.2.1 ([#5180](https://github.com/cookiecutter/cookiecutter-django/pull/5180))
## 2024.06.30
### Updated
- Update django-upgrade to 1.19.0 ([#5171](https://github.com/cookiecutter/cookiecutter-django/pull/5171))
## 2024.06.26
### Fixed
- Fix keywords case warning in Dockerfile ([#5164](https://github.com/cookiecutter/cookiecutter-django/pull/5164))
### Updated
- Update redis to 5.0.7 ([#5170](https://github.com/cookiecutter/cookiecutter-django/pull/5170))
- Update sentry-sdk to 2.7.0 ([#5169](https://github.com/cookiecutter/cookiecutter-django/pull/5169))
## 2024.06.24
### Updated
- Update django-anymail to 11.0 ([#5163](https://github.com/cookiecutter/cookiecutter-django/pull/5163))
- Update coverage to 7.5.4 ([#5162](https://github.com/cookiecutter/cookiecutter-django/pull/5162))
## 2024.06.22
### Updated
- Bump amazon/aws-cli from 2.16.10 to 2.17.0 ([#5161](https://github.com/cookiecutter/cookiecutter-django/pull/5161))
- Auto-update pre-commit hooks ([#5160](https://github.com/cookiecutter/cookiecutter-django/pull/5160))
- Update ruff to 0.4.10 ([#5159](https://github.com/cookiecutter/cookiecutter-django/pull/5159))
## 2024.06.20
### Fixed
- Remove deprecated docker and python tags from GitLab CI config ([#5158](https://github.com/cookiecutter/cookiecutter-django/pull/5158))
## 2024.06.19
### Updated
- Update djangorestframework to 3.15.2 ([#5156](https://github.com/cookiecutter/cookiecutter-django/pull/5156))
- Update django-cors-headers to 4.4.0 ([#5154](https://github.com/cookiecutter/cookiecutter-django/pull/5154))
- Update sentry-sdk to 2.6.0 ([#5153](https://github.com/cookiecutter/cookiecutter-django/pull/5153))
- Update whitenoise to 6.7.0 ([#5155](https://github.com/cookiecutter/cookiecutter-django/pull/5155))
## 2024.06.18
### Updated
- Bump amazon/aws-cli from 2.16.8 to 2.16.10 ([#5149](https://github.com/cookiecutter/cookiecutter-django/pull/5149))
## 2024.06.17
### Updated
- Update django-compressor to 4.5 ([#5145](https://github.com/cookiecutter/cookiecutter-django/pull/5145))
- Update rcssmin to 1.1.2 ([#4614](https://github.com/cookiecutter/cookiecutter-django/pull/4614))
## 2024.06.15
### Changed
- Update start-flower in flower to wait until all celery workers are online ([#5012](https://github.com/cookiecutter/cookiecutter-django/pull/5012))
- Enhancing the security of cookies ([#5102](https://github.com/cookiecutter/cookiecutter-django/pull/5102))
### Updated
- Update django-crispy-forms to 2.2 ([#5143](https://github.com/cookiecutter/cookiecutter-django/pull/5143))
- Update sentry-sdk to 2.5.1 ([#5142](https://github.com/cookiecutter/cookiecutter-django/pull/5142))
- Auto-update pre-commit hooks ([#5140](https://github.com/cookiecutter/cookiecutter-django/pull/5140))
- Update django-allauth to 0.63.3 ([#5111](https://github.com/cookiecutter/cookiecutter-django/pull/5111))
## 2024.06.14
### Updated
- Bump python from 3.12.3-slim-bookworm to 3.12.4-slim-bookworm in /{{cookiecutter.project_slug}}/compose/local/docs ([#5129](https://github.com/cookiecutter/cookiecutter-django/pull/5129))
- Bump python from 3.12.3-slim-bookworm to 3.12.4-slim-bookworm in /{{cookiecutter.project_slug}}/compose/local/django ([#5130](https://github.com/cookiecutter/cookiecutter-django/pull/5130))
- Bump python from 3.12.3-slim-bookworm to 3.12.4-slim-bookworm in /{{cookiecutter.project_slug}}/compose/production/django ([#5132](https://github.com/cookiecutter/cookiecutter-django/pull/5132))
- Bump amazon/aws-cli from 2.16.6 to 2.16.8 in /{{cookiecutter.project_slug}}/compose/production/aws ([#5138](https://github.com/cookiecutter/cookiecutter-django/pull/5138))
- Update ruff to 0.4.9 ([#5139](https://github.com/cookiecutter/cookiecutter-django/pull/5139))
## 2024.06.13
### Updated
- Update redis to 5.0.6 ([#5137](https://github.com/cookiecutter/cookiecutter-django/pull/5137))
## 2024.06.12
### Updated
- Bump amazon/aws-cli Docker image from 2.15.58 to 2.16.6 ([#5135](https://github.com/cookiecutter/cookiecutter-django/pull/5135))
## 2024.06.08
### Changed
- Replace deprecated `uvicorn.workers` with `uvicorn-worker` ([#5110](https://github.com/cookiecutter/cookiecutter-django/pull/5110))
- Change aws-cli docker image to use official amazon image ([#5116](https://github.com/cookiecutter/cookiecutter-django/pull/5116))
## 2024.06.06
### Updated
- Update sentry-sdk to 2.5.0 ([#5126](https://github.com/cookiecutter/cookiecutter-django/pull/5126))
- Update ruff to 0.4.8 ([#5122](https://github.com/cookiecutter/cookiecutter-django/pull/5122))
- Update redis to 5.0.5 ([#5125](https://github.com/cookiecutter/cookiecutter-django/pull/5125))
## 2024.06.04
### Updated
- Update pytest to 8.2.2 ([#5120](https://github.com/cookiecutter/cookiecutter-django/pull/5120))
- Update sh to 2.0.7 ([#5114](https://github.com/cookiecutter/cookiecutter-django/pull/5114))
- Update sentry-sdk to 2.4.0 ([#5119](https://github.com/cookiecutter/cookiecutter-django/pull/5119))
## 2024.06.02
### Updated
- Update uvicorn to 0.30.1 ([#5115](https://github.com/cookiecutter/cookiecutter-django/pull/5115))
## 2024.06.01
### Updated
- Update ruff to 0.4.7 ([#5112](https://github.com/cookiecutter/cookiecutter-django/pull/5112))
## 2024.05.30
### Updated
- Update uvicorn to 0.30.0 ([#5101](https://github.com/cookiecutter/cookiecutter-django/pull/5101))
## 2024.05.29
### Updated
- Update requests to 2.32.3 ([#5108](https://github.com/cookiecutter/cookiecutter-django/pull/5108))
- Update ruff to 0.4.6 ([#5107](https://github.com/cookiecutter/cookiecutter-django/pull/5107))
- Auto-update pre-commit hooks ([#5106](https://github.com/cookiecutter/cookiecutter-django/pull/5106))
- Update coverage to 7.5.3 ([#5104](https://github.com/cookiecutter/cookiecutter-django/pull/5104))
- Update django-upgrade to 1.18.0 ([#5105](https://github.com/cookiecutter/cookiecutter-django/pull/5105))
## 2024.05.27
### Changed
- Rename SendInBlue ESP to Brevo ([#5094](https://github.com/cookiecutter/cookiecutter-django/pull/5094))
### Updated
- Update django-stubs to 5.0.2 ([#5100](https://github.com/cookiecutter/cookiecutter-django/pull/5100))
- Update watchfiles to 0.22.0 ([#5099](https://github.com/cookiecutter/cookiecutter-django/pull/5099))
- Update django-allauth to 0.63.2 ([#5092](https://github.com/cookiecutter/cookiecutter-django/pull/5092))
- Update coverage to 7.5.2 ([#5095](https://github.com/cookiecutter/cookiecutter-django/pull/5095))
- Update django-debug-toolbar to 4.4.2 ([#5098](https://github.com/cookiecutter/cookiecutter-django/pull/5098))
## 2024.05.23
### Updated
- Update sentry-sdk to 2.3.1 ([#5091](https://github.com/cookiecutter/cookiecutter-django/pull/5091))
- Auto-update pre-commit hooks ([#5087](https://github.com/cookiecutter/cookiecutter-django/pull/5087))
- Update ruff to 0.4.5 ([#5086](https://github.com/cookiecutter/cookiecutter-django/pull/5086))
## 2024.05.21 ## 2024.05.21

View File

@ -215,6 +215,20 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>Alexandr Artemyev</td>
<td>
<a href="https://github.com/Mogost">Mogost</a>
</td>
<td>MOGOST</td>
</tr>
<tr>
<td>Ali Shamakhi</td>
<td>
<a href="https://github.com/ali-shamakhi">ali-shamakhi</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>Alvaro [Andor]</td> <td>Alvaro [Andor]</td>
<td> <td>
@ -838,6 +852,13 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>Filipe Nascimento</td>
<td>
<a href="https://github.com/FilipeNas">FilipeNas</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>Florian Idelberger</td> <td>Florian Idelberger</td>
<td> <td>
@ -1118,6 +1139,13 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>Jason Mok</td>
<td>
<a href="https://github.com/jasonmokk">jasonmokk</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>Jens Kaeske</td> <td>Jens Kaeske</td>
<td> <td>
@ -1265,6 +1293,13 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>Kevin Mills</td>
<td>
<a href="https://github.com/millsks">millsks</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>Kevin Ndung&#39;u</td> <td>Kevin Ndung&#39;u</td>
<td> <td>
@ -1398,6 +1433,13 @@ Listed in alphabetical order.
</td> </td>
<td>flyudvik</td> <td>flyudvik</td>
</tr> </tr>
<tr>
<td>Manas Mallick</td>
<td>
<a href="https://github.com/ManDun">ManDun</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>Manjit Pardeshi</td> <td>Manjit Pardeshi</td>
<td> <td>
@ -1566,6 +1608,13 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>milvagox</td>
<td>
<a href="https://github.com/milvagox">milvagox</a>
</td>
<td>milvagox</td>
</tr>
<tr> <tr>
<td>Min ho Kim</td> <td>Min ho Kim</td>
<td> <td>
@ -1692,6 +1741,13 @@ Listed in alphabetical order.
</td> </td>
<td>pamelafox</td> <td>pamelafox</td>
</tr> </tr>
<tr>
<td>Param Kapur</td>
<td>
<a href="https://github.com/paramkpr">paramkpr</a>
</td>
<td>ParamKapur</td>
</tr>
<tr> <tr>
<td>Parbhat Puri</td> <td>Parbhat Puri</td>
<td> <td>

View File

@ -19,7 +19,7 @@ production-ready Django projects quickly.
## Features ## Features
- For Django 4.2 - For Django 5.0
- Works with Python 3.12 - Works with Python 3.12
- Renders Django projects with 100% starting test coverage - Renders Django projects with 100% starting test coverage
- Twitter [Bootstrap](https://github.com/twbs/bootstrap) v5 - Twitter [Bootstrap](https://github.com/twbs/bootstrap) v5
@ -67,7 +67,7 @@ Projects that provide financial support to the maintainers:
### Two Scoops of Django ### Two Scoops of Django
[![Cover of the book "Two Scoops of Django 3.x"](https://www.feldroy.com/static/book-TSD3-800.jpg)](https://www.feldroy.com/two-scoops-press#two-scoops-of-django) [![Cover of the book "Two Scoops of Django 3.x"](https://f004.backblazeb2.com/file/feldroycom/images/book-TSD3-800.jpg)](https://www.feldroy.com/two-scoops-press#two-scoops-of-django)
Two Scoops of Django 3.x is the best ice cream-themed Django reference in the universe! Two Scoops of Django 3.x is the best ice cream-themed Django reference in the universe!
@ -147,7 +147,7 @@ Answer the prompts with your own desired [options](http://cookiecutter-django.re
4 - Mandrill 4 - Mandrill
5 - Postmark 5 - Postmark
6 - Sendgrid 6 - Sendgrid
7 - SendinBlue 7 - Brevo (formerly SendinBlue)
8 - SparkPost 8 - SparkPost
9 - Other SMTP 9 - Other SMTP
Choose from 1, 2, 3, 4, 5, 6, 7, 8, 9 [1]: 1 Choose from 1, 2, 3, 4, 5, 6, 7, 8, 9 [1]: 1
@ -244,6 +244,7 @@ experience better.
## Articles ## Articles
- [Why cookiecutter-django is Essential for Your Next Django Project](https://medium.com/@millsks/why-cookiecutter-django-is-essential-for-your-next-django-project-7d3c00cdce51) - Aug. 4, 2024
- [How to Make Your Own Django Cookiecutter Template!](https://medium.com/@FatemeFouladkar/how-to-make-your-own-django-cookiecutter-template-a753d4cbb8c2) - Aug. 10, 2023 - [How to Make Your Own Django Cookiecutter Template!](https://medium.com/@FatemeFouladkar/how-to-make-your-own-django-cookiecutter-template-a753d4cbb8c2) - Aug. 10, 2023
- [Cookiecutter Django With Amazon RDS](https://haseeburrehman.com/posts/cookiecutter-django-with-amazon-rds/) - Apr, 2, 2021 - [Cookiecutter Django With Amazon RDS](https://haseeburrehman.com/posts/cookiecutter-django-with-amazon-rds/) - Apr, 2, 2021
- [Complete Walkthrough: Blue/Green Deployment to AWS ECS using GitHub actions](https://github.com/Andrew-Chen-Wang/cookiecutter-django-ecs-github) - June 10, 2020 - [Complete Walkthrough: Blue/Green Deployment to AWS ECS using GitHub actions](https://github.com/Andrew-Chen-Wang/cookiecutter-django-ecs-github) - June 10, 2020

View File

@ -27,7 +27,7 @@
"Mandrill", "Mandrill",
"Postmark", "Postmark",
"Sendgrid", "Sendgrid",
"SendinBlue", "Brevo",
"SparkPost", "SparkPost",
"Other SMTP" "Other SMTP"
], ],

View File

@ -43,7 +43,6 @@ Before doing any git commit, `pre-commit`_ should be installed globally on your
Failing to do so will result with a bunch of CI and Linter errors that can be avoided with pre-commit. Failing to do so will result with a bunch of CI and Linter errors that can be avoided with pre-commit.
Run the Stack Run the Stack
------------- -------------
@ -91,7 +90,6 @@ Also, please note that the ``docker exec`` does not work for running management
When ``DEBUG`` is set to ``True``, the host is validated against ``['localhost', '127.0.0.1', '[::1]']``. This is adequate when running a ``virtualenv``. For Docker, in the ``config.settings.local``, add your host development server IP to ``INTERNAL_IPS`` or ``ALLOWED_HOSTS`` if the variable exists. When ``DEBUG`` is set to ``True``, the host is validated against ``['localhost', '127.0.0.1', '[::1]']``. This is adequate when running a ``virtualenv``. For Docker, in the ``config.settings.local``, add your host development server IP to ``INTERNAL_IPS`` or ``ALLOWED_HOSTS`` if the variable exists.
.. _envs: .. _envs:
Configuring the Environment Configuring the Environment
@ -117,8 +115,8 @@ The most important thing for us here now is ``env_file`` section enlisting ``./.
.envs .envs
├── .local ├── .local
   ├── .django ├── .django
   └── .postgres └── .postgres
└── .production └── .production
├── .django ├── .django
└── .postgres └── .postgres
@ -195,7 +193,6 @@ The ``container_name`` from the yml file can be used to check on containers with
$ docker logs <project_slug>_local_celeryworker $ docker logs <project_slug>_local_celeryworker
$ docker top <project_slug>_local_celeryworker $ docker top <project_slug>_local_celeryworker
Notice that the ``container_name`` is generated dynamically using your project slug as a prefix Notice that the ``container_name`` is generated dynamically using your project slug as a prefix
Mailpit Mailpit
@ -245,118 +242,64 @@ The stack comes with a dedicated node service to build the static assets, watch
.. _Sass: https://sass-lang.com/ .. _Sass: https://sass-lang.com/
.. _live reloading: https://browsersync.io .. _live reloading: https://browsersync.io
Developing locally with HTTPS (Optionally) Developing locally with HTTPS
----------------------------- ------------------------------------------
Increasingly it is becoming necessary to develop software in a secure environment in order that there are very few changes when deploying to production. Recently Facebook changed their policies for apps/sites that use Facebook login which requires the use of an HTTPS URL for the OAuth redirect URL. So if you want to use the ``users`` application with a OAuth provider such as Facebook, securing your communication to the local development environment will be necessary. Nginx
In order to create a secure environment, we need to have a trusted SSL certificate installed in our Docker application.
#. **Let's Encrypt**
The official line from Lets Encrypt is:
[For local development section] ... The best option: Generate your own certificate, either self-signed or signed by a local root, and trust it in your operating systems trust store. Then use that certificate in your local web server. See below for details.
See `letsencrypt.org - certificates-for-localhost`_
.. _`letsencrypt.org - certificates-for-localhost`: https://letsencrypt.org/docs/certificates-for-localhost/
#. **mkcert: Valid Https Certificates For Localhost**
`mkcert`_ is a simple by design tool that hides all the arcane knowledge required to generate valid TLS certificates. It works for any hostname or IP, including localhost. It supports macOS, Linux, and Windows, and Firefox, Chrome and Java. It even works on mobile devices with a couple manual steps.
See https://blog.filippo.io/mkcert-valid-https-certificates-for-localhost/
.. _`mkcert`: https://github.com/FiloSottile/mkcert/blob/master/README.md#supported-root-stores
After installing a trusted TLS certificate, configure your docker installation. We are going to configure an ``nginx`` reverse-proxy server. This makes sure that it does not interfere with our ``traefik`` configuration that is reserved for production environments.
These are the places that you should configure to secure your local environment.
certs
~~~~~ ~~~~~
Take the certificates that you generated and place them in a folder called ``certs`` in the project's root folder. Assuming that you registered your local hostname as ``my-dev-env.local``, the certificates you will put in the folder should have the names ``my-dev-env.local.crt`` and ``my-dev-env.local.key``. If you want to add some sort of social authentication with a OAuth provider such as Facebook, securing your communication to the local development environment will be necessary. These providers usually require that you use an HTTPS URL for the OAuth redirect URL for the Facebook login to work appropriately.
docker-compose.local.yml Here is a link to an article on `how to add HTTPS using Nginx`_ to your local docker installation. This also includes how to serve files from the ``media`` location, in the event that you are want to serve user-uploaded content.
~~~~~~~~~
#. Add the ``nginx-proxy`` service. :: .. _`how to add HTTPS using Nginx`: https://afroshok.com/cookiecutter-https
... Webpack
~~~~~~~
nginx-proxy: If you are using Webpack, first install ``mkcert``_. It is a simple by design tool that hides all the arcane knowledge required to generate valid TLS certificates. It works for any hostname or IP, including localhost. It supports macOS, Linux, and Windows, and Firefox, Chrome and Java. It even works on mobile devices with a couple manual steps. See https://blog.filippo.io/mkcert-valid-https-certificates-for-localhost/
image: jwilder/nginx-proxy:alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs
restart: always
depends_on:
- django
... .. _`mkcert`: https://github.com/FiloSottile/mkcert/blob/master/README.md#supported-root-stores
#. Link the ``nginx-proxy`` to ``django`` through environment variables. These are the places that you should configure to secure your local environment. Take the certificates that you generated and place them in a folder called ``certs`` in the project's root folder. Configure an ``nginx`` reverse-proxy server as a ``service`` in the ``docker-compose.local.yml``. This makes sure that it does not interfere with our ``traefik`` configuration that is reserved for production environments.
``django`` already has an ``.env`` file connected to it. Add the following variables. You should do this especially if you are working with a team and you want to keep your local environment details to yourself. Assuming that you registered your local hostname as ``my-dev-env.local``, the certificates you will put in the folder should have the names ``my-dev-env.local.crt`` and ``my-dev-env.local.key``.
:: 1. Add the ``nginx-proxy`` service to the ``docker-compose.local.yml``. ::
# HTTPS nginx-proxy:
# ------------------------------------------------------------------------------ image: jwilder/nginx-proxy:alpine
VIRTUAL_HOST=my-dev-env.local container_name: nginx-proxy
VIRTUAL_PORT=8000 ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs
restart: always
depends_on:
- node
environment:
- VIRTUAL_HOST=my-dev-env.local
- VIRTUAL_PORT=3000
The services run behind the reverse proxy. 2. Add the local secure domain to the ``config/settings/local.py``. You should allow the new hostname ::
config/settings/local.py
~~~~~~~~~~~~~~~~~~~~~~~~
You should allow the new hostname. ::
ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1", "my-dev-env.local"] ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1", "my-dev-env.local"]
3. Add the following configuration to the ``devServer`` section of ``webpack/dev.config.js`` ::
client: {
webSocketURL: 'auto://0.0.0.0:0/ws', // note the `:0` after `0.0.0.0`
},
Rebuild your ``docker`` application. :: Rebuild your ``docker`` application. ::
$ docker compose -f docker-compose.local.yml up -d --build $ docker compose -f docker-compose.local.yml up -d --build
Go to your browser and type in your URL bar ``https://my-dev-env.local`` Go to your browser and type in your URL bar ``https://my-dev-env.local``.
See `https with nginx`_ for more information on this configuration. For more on this configuration, see `https with nginx`_.
.. _`https with nginx`: https://codewithhugo.com/docker-compose-local-https/ .. _`https with nginx`: https://codewithhugo.com/docker-compose-local-https/
.gitignore
~~~~~~~~~~
Add ``certs/*`` to the ``.gitignore`` file. This allows the folder to be included in the repo but its contents to be ignored.
*This configuration is for local development environments only. Do not use this for production since you might expose your local* ``rootCA-key.pem``.
Webpack
~~~~~~~
If you are using Webpack:
1. On the ``nginx-proxy`` service in ``docker-compose.local.yml``, change ``depends_on`` to ``node`` instead of ``django``.
2. On the ``node`` service in ``docker-compose.local.yml``, add the following environment configuration:
::
environment:
- VIRTUAL_HOST=my-dev-env.local
- VIRTUAL_PORT=3000
3. Add the following configuration to the ``devServer`` section of ``webpack/dev.config.js``:
::
client: {
webSocketURL: 'auto://0.0.0.0:0/ws', // note the `:0` after `0.0.0.0`
},

View File

@ -91,7 +91,7 @@ mail_service:
4. Mandrill_ 4. Mandrill_
5. Postmark_ 5. Postmark_
6. SendGrid_ 6. SendGrid_
7. SendinBlue_ 7. `Brevo (formerly SendinBlue)`_
8. SparkPost_ 8. SparkPost_
9. `Other SMTP`_ 9. `Other SMTP`_
@ -174,7 +174,7 @@ debug:
.. _Mandrill: http://mandrill.com .. _Mandrill: http://mandrill.com
.. _Postmark: https://postmarkapp.com .. _Postmark: https://postmarkapp.com
.. _SendGrid: https://sendgrid.com .. _SendGrid: https://sendgrid.com
.. _SendinBlue: https://www.sendinblue.com .. _Brevo (formerly SendinBlue): https://www.brevo.com
.. _SparkPost: https://www.sparkpost.com .. _SparkPost: https://www.sparkpost.com
.. _Other SMTP: https://anymail.readthedocs.io/en/stable/ .. _Other SMTP: https://anymail.readthedocs.io/en/stable/

View File

@ -1,3 +1,3 @@
sphinx==7.3.7 sphinx==7.4.7
sphinx-rtd-theme==2.0.0 sphinx-rtd-theme==2.0.0
myst-parser==3.0.1 myst-parser==4.0.0

View File

@ -69,8 +69,8 @@ SENDGRID_API_KEY SENDGRID_API_KEY n/a
SENDGRID_GENERATE_MESSAGE_ID True n/a raises error SENDGRID_GENERATE_MESSAGE_ID True n/a raises error
SENDGRID_MERGE_FIELD_FORMAT None n/a raises error SENDGRID_MERGE_FIELD_FORMAT None n/a raises error
SENDGRID_API_URL n/a n/a "https://api.sendgrid.com/v3/" SENDGRID_API_URL n/a n/a "https://api.sendgrid.com/v3/"
SENDINBLUE_API_KEY SENDINBLUE_API_KEY n/a raises error BREVO_API_KEY BREVO_API_KEY n/a raises error
SENDINBLUE_API_URL n/a n/a "https://api.sendinblue.com/v3/" BREVO_API_URL n/a n/a "https://api.brevo.com/v3/"
SPARKPOST_API_KEY SPARKPOST_API_KEY n/a raises error SPARKPOST_API_KEY SPARKPOST_API_KEY n/a raises error
SPARKPOST_API_URL n/a n/a "https://api.sparkpost.com/api/v1" SPARKPOST_API_URL n/a n/a "https://api.sparkpost.com/api/v1"
======================================= =========================== ============================================== ====================================================================== ======================================= =========================== ============================================== ======================================================================

View File

@ -1,26 +1,26 @@
cookiecutter==2.6.0 cookiecutter==2.6.0
sh==2.0.6; sys_platform != "win32" sh==2.0.7; sys_platform != "win32"
binaryornot==0.4.4 binaryornot==0.4.4
# Code quality # Code quality
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
ruff==0.4.4 ruff==0.6.1
django-upgrade==1.17.0 django-upgrade==1.20.0
djlint==1.34.1 djlint==1.34.1
pre-commit==3.7.1 pre-commit==3.8.0
# Testing # Testing
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
tox==4.15.0 tox==4.18.0
pytest==8.2.1 pytest==8.3.2
pytest-xdist==3.6.1 pytest-xdist==3.6.1
pytest-cookies==0.7.0 pytest-cookies==0.7.0
pytest-instafail==0.5.0 pytest-instafail==0.5.0
pyyaml==6.0.1 pyyaml==6.0.2
# Scripting # Scripting
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
PyGithub==2.3.0 PyGithub==2.3.0
gitpython==3.1.43 gitpython==3.1.43
jinja2==3.1.4 jinja2==3.1.4
requests==2.32.2 requests==2.32.3

View File

@ -5,7 +5,7 @@ except ImportError:
from distutils.core import setup from distutils.core import setup
# We use calendar versioning # We use calendar versioning
version = "2024.05.21" version = "2024.08.19"
with open("README.md") as readme_file: with open("README.md") as readme_file:
long_description = readme_file.read() long_description = readme_file.read()
@ -24,7 +24,7 @@ setup(
classifiers=[ classifiers=[
"Development Status :: 4 - Beta", "Development Status :: 4 - Beta",
"Environment :: Console", "Environment :: Console",
"Framework :: Django :: 4.2", "Framework :: Django :: 5.0",
"Intended Audience :: Developers", "Intended Audience :: Developers",
"Natural Language :: English", "Natural Language :: English",
"License :: OSI Approved :: BSD License", "License :: OSI Approved :: BSD License",

View File

@ -73,7 +73,7 @@ SUPPORTED_COMBINATIONS = [
{"cloud_provider": "None", "use_whitenoise": "y", "mail_service": "Mandrill"}, {"cloud_provider": "None", "use_whitenoise": "y", "mail_service": "Mandrill"},
{"cloud_provider": "None", "use_whitenoise": "y", "mail_service": "Postmark"}, {"cloud_provider": "None", "use_whitenoise": "y", "mail_service": "Postmark"},
{"cloud_provider": "None", "use_whitenoise": "y", "mail_service": "Sendgrid"}, {"cloud_provider": "None", "use_whitenoise": "y", "mail_service": "Sendgrid"},
{"cloud_provider": "None", "use_whitenoise": "y", "mail_service": "SendinBlue"}, {"cloud_provider": "None", "use_whitenoise": "y", "mail_service": "Brevo"},
{"cloud_provider": "None", "use_whitenoise": "y", "mail_service": "SparkPost"}, {"cloud_provider": "None", "use_whitenoise": "y", "mail_service": "SparkPost"},
{"cloud_provider": "None", "use_whitenoise": "y", "mail_service": "Other SMTP"}, {"cloud_provider": "None", "use_whitenoise": "y", "mail_service": "Other SMTP"},
# Note: cloud_provider=None AND use_whitenoise=n is not supported # Note: cloud_provider=None AND use_whitenoise=n is not supported
@ -83,7 +83,7 @@ SUPPORTED_COMBINATIONS = [
{"cloud_provider": "AWS", "mail_service": "Mandrill"}, {"cloud_provider": "AWS", "mail_service": "Mandrill"},
{"cloud_provider": "AWS", "mail_service": "Postmark"}, {"cloud_provider": "AWS", "mail_service": "Postmark"},
{"cloud_provider": "AWS", "mail_service": "Sendgrid"}, {"cloud_provider": "AWS", "mail_service": "Sendgrid"},
{"cloud_provider": "AWS", "mail_service": "SendinBlue"}, {"cloud_provider": "AWS", "mail_service": "Brevo"},
{"cloud_provider": "AWS", "mail_service": "SparkPost"}, {"cloud_provider": "AWS", "mail_service": "SparkPost"},
{"cloud_provider": "AWS", "mail_service": "Other SMTP"}, {"cloud_provider": "AWS", "mail_service": "Other SMTP"},
{"cloud_provider": "GCP", "mail_service": "Mailgun"}, {"cloud_provider": "GCP", "mail_service": "Mailgun"},
@ -91,7 +91,7 @@ SUPPORTED_COMBINATIONS = [
{"cloud_provider": "GCP", "mail_service": "Mandrill"}, {"cloud_provider": "GCP", "mail_service": "Mandrill"},
{"cloud_provider": "GCP", "mail_service": "Postmark"}, {"cloud_provider": "GCP", "mail_service": "Postmark"},
{"cloud_provider": "GCP", "mail_service": "Sendgrid"}, {"cloud_provider": "GCP", "mail_service": "Sendgrid"},
{"cloud_provider": "GCP", "mail_service": "SendinBlue"}, {"cloud_provider": "GCP", "mail_service": "Brevo"},
{"cloud_provider": "GCP", "mail_service": "SparkPost"}, {"cloud_provider": "GCP", "mail_service": "SparkPost"},
{"cloud_provider": "GCP", "mail_service": "Other SMTP"}, {"cloud_provider": "GCP", "mail_service": "Other SMTP"},
{"cloud_provider": "Azure", "mail_service": "Mailgun"}, {"cloud_provider": "Azure", "mail_service": "Mailgun"},
@ -99,7 +99,7 @@ SUPPORTED_COMBINATIONS = [
{"cloud_provider": "Azure", "mail_service": "Mandrill"}, {"cloud_provider": "Azure", "mail_service": "Mandrill"},
{"cloud_provider": "Azure", "mail_service": "Postmark"}, {"cloud_provider": "Azure", "mail_service": "Postmark"},
{"cloud_provider": "Azure", "mail_service": "Sendgrid"}, {"cloud_provider": "Azure", "mail_service": "Sendgrid"},
{"cloud_provider": "Azure", "mail_service": "SendinBlue"}, {"cloud_provider": "Azure", "mail_service": "Brevo"},
{"cloud_provider": "Azure", "mail_service": "SparkPost"}, {"cloud_provider": "Azure", "mail_service": "SparkPost"},
{"cloud_provider": "Azure", "mail_service": "Other SMTP"}, {"cloud_provider": "Azure", "mail_service": "Other SMTP"},
# Note: cloud_providers GCP, Azure, and None # Note: cloud_providers GCP, Azure, and None
@ -230,7 +230,7 @@ def test_django_upgrade_passes(cookies, context_override):
try: try:
sh.django_upgrade( sh.django_upgrade(
"--target-version", "--target-version",
"4.2", "5.0",
*python_files, *python_files,
_cwd=str(result.project_path), _cwd=str(result.project_path),
) )

View File

@ -28,8 +28,8 @@ POSTMARK_SERVER_TOKEN=
SENDGRID_API_KEY= SENDGRID_API_KEY=
SENDGRID_GENERATE_MESSAGE_ID=True SENDGRID_GENERATE_MESSAGE_ID=True
SENDGRID_MERGE_FIELD_FORMAT=None SENDGRID_MERGE_FIELD_FORMAT=None
{% elif cookiecutter.mail_service == 'SendinBlue' %} {% elif cookiecutter.mail_service == 'Brevo' %}
SENDINBLUE_API_KEY= BREVO_API_KEY=
{% elif cookiecutter.mail_service == 'SparkPost' %} {% elif cookiecutter.mail_service == 'SparkPost' %}
SPARKPOST_API_KEY= SPARKPOST_API_KEY=
{% endif %} {% endif %}

View File

@ -28,8 +28,6 @@ pytest:
stage: test stage: test
{%- if cookiecutter.use_docker == 'y' %} {%- if cookiecutter.use_docker == 'y' %}
image: docker:25.0 image: docker:25.0
tags:
- docker
services: services:
- docker:dind - docker:dind
before_script: before_script:
@ -42,8 +40,6 @@ pytest:
- docker compose -f docker-compose.local.yml run django pytest - docker compose -f docker-compose.local.yml run django pytest
{%- else %} {%- else %}
image: python:3.12 image: python:3.12
tags:
- python
services: services:
- postgres:{{ cookiecutter.postgresql_version }} - postgres:{{ cookiecutter.postgresql_version }}
variables: variables:

View File

@ -28,14 +28,14 @@ repos:
exclude: '{{cookiecutter.project_slug}}/templates/' exclude: '{{cookiecutter.project_slug}}/templates/'
- repo: https://github.com/adamchainz/django-upgrade - repo: https://github.com/adamchainz/django-upgrade
rev: '1.17.0' rev: '1.20.0'
hooks: hooks:
- id: django-upgrade - id: django-upgrade
args: ['--target-version', '4.2'] args: ['--target-version', '5.0']
# Run the Ruff linter. # Run the Ruff linter.
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.4 rev: v0.6.1
hooks: hooks:
# Linter # Linter
- id: ruff - id: ruff

View File

@ -1,6 +1,6 @@
release: python manage.py migrate release: python manage.py migrate
{%- if cookiecutter.use_async == "y" %} {%- if cookiecutter.use_async == "y" %}
web: gunicorn config.asgi:application -k uvicorn.workers.UvicornWorker web: gunicorn config.asgi:application -k uvicorn_worker.UvicornWorker
{%- else %} {%- else %}
web: gunicorn config.wsgi:application web: gunicorn config.wsgi:application
{%- endif %} {%- endif %}

View File

@ -1,8 +1,8 @@
# define an alias for the specific python version used in this file. # define an alias for the specific python version used in this file.
FROM docker.io/python:3.12.3-slim-bookworm as python FROM docker.io/python:3.12.5-slim-bookworm AS python
# Python build stage # Python build stage
FROM python as python-build-stage FROM python AS python-build-stage
ARG BUILD_ENVIRONMENT=local ARG BUILD_ENVIRONMENT=local
@ -22,14 +22,14 @@ RUN pip wheel --wheel-dir /usr/src/app/wheels \
# Python 'run' stage # Python 'run' stage
FROM python as python-run-stage FROM python AS python-run-stage
ARG BUILD_ENVIRONMENT=local ARG BUILD_ENVIRONMENT=local
ARG APP_HOME=/app ARG APP_HOME=/app
ENV PYTHONUNBUFFERED 1 ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONDONTWRITEBYTECODE=1
ENV BUILD_ENV ${BUILD_ENVIRONMENT} ENV BUILD_ENV=${BUILD_ENVIRONMENT}
WORKDIR ${APP_HOME} WORKDIR ${APP_HOME}

View File

@ -3,6 +3,14 @@
set -o errexit set -o errexit
set -o nounset set -o nounset
until timeout 10 celery -A config.celery_app inspect ping; do
>&2 echo "Celery workers not available"
done
echo 'Starting flower'
exec watchfiles --filter python celery.__main__.main \ exec watchfiles --filter python celery.__main__.main \
--args \ --args \
"-A config.celery_app -b \"${CELERY_BROKER_URL}\" flower --basic_auth=\"${CELERY_FLOWER_USER}:${CELERY_FLOWER_PASSWORD}\"" "-A config.celery_app -b \"${CELERY_BROKER_URL}\" flower --basic_auth=\"${CELERY_FLOWER_USER}:${CELERY_FLOWER_PASSWORD}\""

View File

@ -1,11 +1,11 @@
# define an alias for the specific python version used in this file. # define an alias for the specific python version used in this file.
FROM docker.io/python:3.12.3-slim-bookworm as python FROM docker.io/python:3.12.5-slim-bookworm AS python
# Python build stage # Python build stage
FROM python as python-build-stage FROM python AS python-build-stage
ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONDONTWRITEBYTECODE=1
RUN apt-get update && apt-get install --no-install-recommends -y \ RUN apt-get update && apt-get install --no-install-recommends -y \
# dependencies for building Python packages # dependencies for building Python packages
@ -26,11 +26,11 @@ RUN pip wheel --no-cache-dir --wheel-dir /usr/src/app/wheels \
# Python 'run' stage # Python 'run' stage
FROM python as python-run-stage FROM python AS python-run-stage
ARG BUILD_ENVIRONMENT ARG BUILD_ENVIRONMENT
ENV PYTHONUNBUFFERED 1 ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONDONTWRITEBYTECODE=1
RUN apt-get update && apt-get install --no-install-recommends -y \ RUN apt-get update && apt-get install --no-install-recommends -y \
# To run the Makefile # To run the Makefile

View File

@ -6,4 +6,4 @@ COPY ./package.json /app
RUN npm install && npm cache clean --force RUN npm install && npm cache clean --force
ENV PATH ./node_modules/.bin/:$PATH ENV PATH=./node_modules/.bin/:$PATH

View File

@ -1,4 +1,8 @@
FROM docker.io/garland/aws-cli-docker:1.16.140 FROM docker.io/amazon/aws-cli:2.17.0
# Clear entrypoint from the base image, otherwise it's always calling the aws CLI
ENTRYPOINT []
CMD ["/bin/bash"]
COPY ./compose/production/aws/maintenance /usr/local/bin/maintenance COPY ./compose/production/aws/maintenance /usr/local/bin/maintenance
COPY ./compose/production/postgres/maintenance/_sourced /usr/local/bin/maintenance/_sourced COPY ./compose/production/postgres/maintenance/_sourced /usr/local/bin/maintenance/_sourced

View File

@ -1,5 +1,5 @@
{% if cookiecutter.frontend_pipeline in ['Gulp', 'Webpack'] -%} {% if cookiecutter.frontend_pipeline in ['Gulp', 'Webpack'] -%}
FROM docker.io/node:20-bookworm-slim as client-builder FROM docker.io/node:20-bookworm-slim AS client-builder
ARG APP_HOME=/app ARG APP_HOME=/app
WORKDIR ${APP_HOME} WORKDIR ${APP_HOME}
@ -25,10 +25,10 @@ RUN npm run build
{%- endif %} {%- endif %}
# define an alias for the specific python version used in this file. # define an alias for the specific python version used in this file.
FROM docker.io/python:3.12.3-slim-bookworm as python FROM docker.io/python:3.12.5-slim-bookworm AS python
# Python build stage # Python build stage
FROM python as python-build-stage FROM python AS python-build-stage
ARG BUILD_ENVIRONMENT=production ARG BUILD_ENVIRONMENT=production
@ -48,14 +48,14 @@ RUN pip wheel --wheel-dir /usr/src/app/wheels \
# Python 'run' stage # Python 'run' stage
FROM python as python-run-stage FROM python AS python-run-stage
ARG BUILD_ENVIRONMENT=production ARG BUILD_ENVIRONMENT=production
ARG APP_HOME=/app ARG APP_HOME=/app
ENV PYTHONUNBUFFERED 1 ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONDONTWRITEBYTECODE=1
ENV BUILD_ENV ${BUILD_ENVIRONMENT} ENV BUILD_ENV=${BUILD_ENVIRONMENT}
WORKDIR ${APP_HOME} WORKDIR ${APP_HOME}

View File

@ -4,6 +4,14 @@ set -o errexit
set -o nounset set -o nounset
until timeout 10 celery -A config.celery_app inspect ping; do
>&2 echo "Celery workers not available"
done
echo 'Starting flower'
exec celery \ exec celery \
-A config.celery_app \ -A config.celery_app \
-b "${CELERY_BROKER_URL}" \ -b "${CELERY_BROKER_URL}" \

View File

@ -28,7 +28,7 @@ if compress_enabled; then
fi fi
{%- endif %} {%- endif %}
{%- if cookiecutter.use_async == 'y' %} {%- if cookiecutter.use_async == 'y' %}
exec /usr/local/bin/gunicorn config.asgi --bind 0.0.0.0:5000 --chdir=/app -k uvicorn.workers.UvicornWorker exec /usr/local/bin/gunicorn config.asgi --bind 0.0.0.0:5000 --chdir=/app -k uvicorn_worker.UvicornWorker
{%- else %} {%- else %}
exec /usr/local/bin/gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app exec /usr/local/bin/gunicorn config.wsgi --bind 0.0.0.0:5000 --chdir=/app
{%- endif %} {%- endif %}

View File

@ -1,4 +1,4 @@
FROM docker.io/traefik:2.11.2 FROM docker.io/traefik:3.1.2
RUN mkdir -p /etc/traefik/acme \ RUN mkdir -p /etc/traefik/acme \
&& touch /etc/traefik/acme/acme.json \ && touch /etc/traefik/acme/acme.json \
&& chmod 600 /etc/traefik/acme/acme.json && chmod 600 /etc/traefik/acme/acme.json

View File

@ -55,8 +55,12 @@ SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True) SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True)
# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-secure # https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-secure
SESSION_COOKIE_SECURE = True SESSION_COOKIE_SECURE = True
# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-name
SESSION_COOKIE_NAME = "__Secure-sessionid"
# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-secure # https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-secure
CSRF_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True
# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-name
CSRF_COOKIE_NAME = "__Secure-csrftoken"
# https://docs.djangoproject.com/en/dev/topics/security/#ssl-https # https://docs.djangoproject.com/en/dev/topics/security/#ssl-https
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-seconds # https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-seconds
# TODO: set this to 60 seconds first and then to 518400 once you prove the former works # TODO: set this to 60 seconds first and then to 518400 once you prove the former works
@ -194,13 +198,13 @@ STORAGES = {
{%- if cookiecutter.cloud_provider == 'AWS' %} {%- if cookiecutter.cloud_provider == 'AWS' %}
MEDIA_URL = f"https://{aws_s3_domain}/media/" MEDIA_URL = f"https://{aws_s3_domain}/media/"
{%- if cookiecutter.use_whitenoise == 'n' %} {%- if cookiecutter.use_whitenoise == 'n' %}
COLLECTFAST_STRATEGY = "collectfast.strategies.boto3.Boto3Strategy" COLLECTFASTA_STRATEGY = "collectfasta.strategies.boto3.Boto3Strategy"
STATIC_URL = f"https://{aws_s3_domain}/static/" STATIC_URL = f"https://{aws_s3_domain}/static/"
{%- endif %} {%- endif %}
{%- elif cookiecutter.cloud_provider == 'GCP' %} {%- elif cookiecutter.cloud_provider == 'GCP' %}
MEDIA_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/" MEDIA_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/"
{%- if cookiecutter.use_whitenoise == 'n' %} {%- if cookiecutter.use_whitenoise == 'n' %}
COLLECTFAST_STRATEGY = "collectfast.strategies.gcloud.GoogleCloudStrategy" COLLECTFASTA_STRATEGY = "collectfasta.strategies.gcloud.GoogleCloudStrategy"
STATIC_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/static/" STATIC_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/static/"
{%- endif %} {%- endif %}
{%- elif cookiecutter.cloud_provider == 'Azure' %} {%- elif cookiecutter.cloud_provider == 'Azure' %}
@ -276,12 +280,12 @@ ANYMAIL = {
"SENDGRID_API_KEY": env("SENDGRID_API_KEY"), "SENDGRID_API_KEY": env("SENDGRID_API_KEY"),
"SENDGRID_API_URL": env("SENDGRID_API_URL", default="https://api.sendgrid.com/v3/"), "SENDGRID_API_URL": env("SENDGRID_API_URL", default="https://api.sendgrid.com/v3/"),
} }
{%- elif cookiecutter.mail_service == 'SendinBlue' %} {%- elif cookiecutter.mail_service == 'Brevo' %}
# https://anymail.readthedocs.io/en/stable/esps/sendinblue/ # https://anymail.readthedocs.io/en/stable/esps/brevo/
EMAIL_BACKEND = "anymail.backends.sendinblue.EmailBackend" EMAIL_BACKEND = "anymail.backends.brevo.EmailBackend"
ANYMAIL = { ANYMAIL = {
"SENDINBLUE_API_KEY": env("SENDINBLUE_API_KEY"), "BREVO_API_KEY": env("BREVO_API_KEY"),
"SENDINBLUE_API_URL": env("SENDINBLUE_API_URL", default="https://api.sendinblue.com/v3/"), "BREVO_API_URL": env("BREVO_API_URL", default="https://api.brevo.com/v3/"),
} }
{%- elif cookiecutter.mail_service == 'SparkPost' %} {%- elif cookiecutter.mail_service == 'SparkPost' %}
# https://anymail.readthedocs.io/en/stable/esps/sparkpost/ # https://anymail.readthedocs.io/en/stable/esps/sparkpost/
@ -325,10 +329,10 @@ COMPRESS_FILTERS = {
} }
{% endif %} {% endif %}
{%- if cookiecutter.use_whitenoise == 'n' -%} {%- if cookiecutter.use_whitenoise == 'n' -%}
# Collectfast # Collectfasta
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# https://github.com/antonagestam/collectfast#installation # https://github.com/jasongi/collectfasta#installation
INSTALLED_APPS = ["collectfast", *INSTALLED_APPS] INSTALLED_APPS = ["collectfasta", *INSTALLED_APPS]
{% endif %} {% endif %}
# LOGGING # LOGGING
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -106,7 +106,7 @@ function imgCompression() {
function asyncRunServer() { function asyncRunServer() {
const cmd = spawn( const cmd = spawn(
'gunicorn', 'gunicorn',
['config.asgi', '-k', 'uvicorn.workers.UvicornWorker', '--reload'], ['config.asgi', '-k', 'uvicorn_worker.UvicornWorker', '--reload'],
{stdio: 'inherit'}, {stdio: 'inherit'},
); );
cmd.on('close', function (code) { cmd.on('close', function (code) {

View File

@ -3,7 +3,7 @@
Start by configuring the `LANGUAGES` settings in `base.py`, by uncommenting languages you are willing to support. Then, translations strings will be placed in this folder when running: Start by configuring the `LANGUAGES` settings in `base.py`, by uncommenting languages you are willing to support. Then, translations strings will be placed in this folder when running:
```bash ```bash
{% if cookiecutter.use_docker == 'y' %}docker compose -f docker-compose.local.yml run --rm django {% endif %}python manage.py makemessages -all --no-location {% if cookiecutter.use_docker == 'y' %}docker compose -f docker-compose.local.yml run --rm django {% endif %}python manage.py makemessages --all --no-location
``` ```
This should generate `django.po` (stands for Portable Object) files under each locale `<locale name>/LC_MESSAGES/django.po`. Each translatable string in the codebase is collected with its `msgid` and need to be translated as `msgstr`, for example: This should generate `django.po` (stands for Portable Object) files under each locale `<locale name>/LC_MESSAGES/django.po`. Each translatable string in the codebase is collected with its `msgid` and need to be translated as `msgstr`, for example:

View File

@ -59,36 +59,12 @@ indent_size = 2
indent_size = 2 indent_size = 2
[tool.ruff] [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" target-version = "py312"
# Exclude a variety of commonly ignored directories.
extend-exclude = [
"*/migrations/*.py",
"staticfiles/*",
]
[tool.ruff.lint] [tool.ruff.lint]
select = [ select = [
@ -145,33 +121,22 @@ select = [
"PERF", "PERF",
# "FURB", # "FURB",
# "LOG", # "LOG",
"RUF" "RUF",
] ]
ignore = [ ignore = [
"S101", # Use of assert detected https://docs.astral.sh/ruff/rules/assert/ "S101", # Use of assert detected https://docs.astral.sh/ruff/rules/assert/
"RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar`
"SIM102", # sometimes it's better to nest "SIM102", # sometimes it's better to nest
"UP038" # Checks for uses of isinstance/issubclass that take a tuple "UP038", # Checks for uses of isinstance/issubclass that take a tuple
# of types for comparison. # of types for comparison.
# Deactivated because it can make the code slow: # Deactivated because it can make the code slow:
# https://github.com/astral-sh/ruff/issues/7871 # https://github.com/astral-sh/ruff/issues/7871
] ]
# Allow fix for all enabled rules (when `--fix`) is provided. # The fixes in extend-unsafe-fixes will require
fixable = ["ALL"]
unfixable = []
# The fixes in extend-unsafe-fixes will require
# provide the `--unsafe-fixes` flag when fixing. # provide the `--unsafe-fixes` flag when fixing.
extend-unsafe-fixes = [ extend-unsafe-fixes = [
"UP038" "UP038",
] ]
# 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] [tool.ruff.lint.isort]
force-single-line = true force-single-line = true

View File

@ -1,19 +1,19 @@
python-slugify==8.0.4 # https://github.com/un33k/python-slugify python-slugify==8.0.4 # https://github.com/un33k/python-slugify
Pillow==10.3.0 # https://github.com/python-pillow/Pillow Pillow==10.4.0 # https://github.com/python-pillow/Pillow
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %} {%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
{%- if cookiecutter.windows == 'y' and cookiecutter.use_docker == 'n' %} {%- if cookiecutter.windows == 'y' and cookiecutter.use_docker == 'n' %}
rcssmin==1.1.0 --install-option="--without-c-extensions" # https://github.com/ndparker/rcssmin rcssmin==1.1.2 --install-option="--without-c-extensions" # https://github.com/ndparker/rcssmin
{%- else %} {%- else %}
rcssmin==1.1.1 # https://github.com/ndparker/rcssmin rcssmin==1.1.2 # https://github.com/ndparker/rcssmin
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
argon2-cffi==23.1.0 # https://github.com/hynek/argon2_cffi argon2-cffi==23.1.0 # https://github.com/hynek/argon2_cffi
{%- if cookiecutter.use_whitenoise == 'y' %} {%- if cookiecutter.use_whitenoise == 'y' %}
whitenoise==6.6.0 # https://github.com/evansd/whitenoise whitenoise==6.7.0 # https://github.com/evansd/whitenoise
{%- endif %} {%- endif %}
redis==5.0.4 # https://github.com/redis/redis-py redis==5.0.8 # https://github.com/redis/redis-py
{%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %} {%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %}
hiredis==2.3.2 # https://github.com/redis/hiredis-py hiredis==3.0.0 # https://github.com/redis/hiredis-py
{%- endif %} {%- endif %}
{%- if cookiecutter.use_celery == "y" %} {%- if cookiecutter.use_celery == "y" %}
celery==5.4.0 # pyup: < 6.0 # https://github.com/celery/celery celery==5.4.0 # pyup: < 6.0 # https://github.com/celery/celery
@ -23,25 +23,26 @@ flower==2.0.1 # https://github.com/mher/flower
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
{%- if cookiecutter.use_async == 'y' %} {%- if cookiecutter.use_async == 'y' %}
uvicorn[standard]==0.29.0 # https://github.com/encode/uvicorn uvicorn[standard]==0.30.6 # https://github.com/encode/uvicorn
uvicorn-worker==0.2.0 # https://github.com/Kludex/uvicorn-worker
{%- endif %} {%- endif %}
# Django # Django
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
django==4.2.13 # pyup: < 5.0 # https://www.djangoproject.com/ django==5.0.8 # pyup: < 5.1 # https://www.djangoproject.com/
django-environ==0.11.2 # https://github.com/joke2k/django-environ django-environ==0.11.2 # https://github.com/joke2k/django-environ
django-model-utils==4.5.1 # https://github.com/jazzband/django-model-utils django-model-utils==4.5.1 # https://github.com/jazzband/django-model-utils
django-allauth[mfa]==0.63.1 # https://github.com/pennersr/django-allauth django-allauth[mfa]==64.1.0 # https://github.com/pennersr/django-allauth
django-crispy-forms==2.1 # https://github.com/django-crispy-forms/django-crispy-forms django-crispy-forms==2.3 # https://github.com/django-crispy-forms/django-crispy-forms
crispy-bootstrap5==2024.2 # 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' %} {%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
django-compressor==4.4 # https://github.com/django-compressor/django-compressor django-compressor==4.5.1 # https://github.com/django-compressor/django-compressor
{%- endif %} {%- endif %}
django-redis==5.4.0 # https://github.com/jazzband/django-redis django-redis==5.4.0 # https://github.com/jazzband/django-redis
{%- if cookiecutter.use_drf == 'y' %} {%- if cookiecutter.use_drf == 'y' %}
# Django REST Framework # Django REST Framework
djangorestframework==3.15.1 # https://github.com/encode/django-rest-framework djangorestframework==3.15.2 # https://github.com/encode/django-rest-framework
django-cors-headers==4.3.1 # https://github.com/adamchainz/django-cors-headers django-cors-headers==4.4.0 # https://github.com/adamchainz/django-cors-headers
# DRF-spectacular for api documentation # DRF-spectacular for api documentation
drf-spectacular==0.27.2 # https://github.com/tfranzel/drf-spectacular drf-spectacular==0.27.2 # https://github.com/tfranzel/drf-spectacular
{%- endif %} {%- endif %}

View File

@ -3,9 +3,9 @@
Werkzeug[watchdog]==3.0.3 # https://github.com/pallets/werkzeug Werkzeug[watchdog]==3.0.3 # https://github.com/pallets/werkzeug
ipdb==0.13.13 # https://github.com/gotcha/ipdb ipdb==0.13.13 # https://github.com/gotcha/ipdb
{%- if cookiecutter.use_docker == 'y' %} {%- if cookiecutter.use_docker == 'y' %}
psycopg[c]==3.1.19 # https://github.com/psycopg/psycopg psycopg[c]==3.2.1 # https://github.com/psycopg/psycopg
{%- else %} {%- else %}
psycopg[binary]==3.1.19 # https://github.com/psycopg/psycopg psycopg[binary]==3.2.1 # https://github.com/psycopg/psycopg
{%- endif %} {%- endif %}
{%- if cookiecutter.use_async == 'y' or cookiecutter.use_celery == 'y' %} {%- if cookiecutter.use_async == 'y' or cookiecutter.use_celery == 'y' %}
watchfiles==0.21.0 # https://github.com/samuelcolvin/watchfiles watchfiles==0.21.0 # https://github.com/samuelcolvin/watchfiles
@ -13,31 +13,31 @@ watchfiles==0.21.0 # https://github.com/samuelcolvin/watchfiles
# Testing # Testing
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
mypy==1.10.0 # https://github.com/python/mypy mypy==1.11.1 # https://github.com/python/mypy
django-stubs[compatible-mypy]==5.0.0 # https://github.com/typeddjango/django-stubs django-stubs[compatible-mypy]==5.0.4 # https://github.com/typeddjango/django-stubs
pytest==8.2.1 # https://github.com/pytest-dev/pytest pytest==8.3.2 # https://github.com/pytest-dev/pytest
pytest-sugar==1.0.0 # https://github.com/Frozenball/pytest-sugar pytest-sugar==1.0.0 # https://github.com/Frozenball/pytest-sugar
{%- if cookiecutter.use_drf == "y" %} {%- if cookiecutter.use_drf == "y" %}
djangorestframework-stubs[compatible-mypy]==3.15.0 # https://github.com/typeddjango/djangorestframework-stubs djangorestframework-stubs==3.15.0 # https://github.com/typeddjango/djangorestframework-stubs
{%- endif %} {%- endif %}
# Documentation # Documentation
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
sphinx==7.3.7 # https://github.com/sphinx-doc/sphinx sphinx==7.4.7 # https://github.com/sphinx-doc/sphinx
sphinx-autobuild==2024.4.16 # https://github.com/GaretJax/sphinx-autobuild sphinx-autobuild==2024.4.16 # https://github.com/GaretJax/sphinx-autobuild
# Code quality # Code quality
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
ruff==0.4.4 # https://github.com/astral-sh/ruff ruff==0.6.1 # https://github.com/astral-sh/ruff
coverage==7.5.1 # https://github.com/nedbat/coveragepy coverage==7.6.1 # https://github.com/nedbat/coveragepy
djlint==1.34.1 # https://github.com/Riverside-Healthcare/djLint djlint==1.34.1 # https://github.com/Riverside-Healthcare/djLint
pre-commit==3.7.1 # https://github.com/pre-commit/pre-commit pre-commit==3.8.0 # https://github.com/pre-commit/pre-commit
# Django # Django
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
factory-boy==3.3.0 # https://github.com/FactoryBoy/factory_boy factory-boy==3.3.1 # https://github.com/FactoryBoy/factory_boy
django-debug-toolbar==4.3.0 # https://github.com/jazzband/django-debug-toolbar django-debug-toolbar==4.4.6 # https://github.com/jazzband/django-debug-toolbar
django-extensions==3.2.3 # https://github.com/django-extensions/django-extensions django-extensions==3.2.3 # https://github.com/django-extensions/django-extensions
django-coverage-plugin==3.1.0 # https://github.com/nedbat/django_coverage_plugin django-coverage-plugin==3.1.0 # https://github.com/nedbat/django_coverage_plugin
pytest-django==4.8.0 # https://github.com/pytest-dev/pytest-django pytest-django==4.8.0 # https://github.com/pytest-dev/pytest-django

View File

@ -2,43 +2,43 @@
-r base.txt -r base.txt
gunicorn==22.0.0 # https://github.com/benoitc/gunicorn gunicorn==23.0.0 # https://github.com/benoitc/gunicorn
psycopg[c]==3.1.19 # https://github.com/psycopg/psycopg psycopg[c]==3.2.1 # https://github.com/psycopg/psycopg
{%- if cookiecutter.use_whitenoise == 'n' %} {%- if cookiecutter.use_whitenoise == 'n' %}
Collectfast==2.2.0 # https://github.com/antonagestam/collectfast Collectfasta==3.2.0 # https://github.com/jasongi/collectfasta
{%- endif %} {%- endif %}
{%- if cookiecutter.use_sentry == "y" %} {%- if cookiecutter.use_sentry == "y" %}
sentry-sdk==2.2.1 # https://github.com/getsentry/sentry-python sentry-sdk==2.13.0 # https://github.com/getsentry/sentry-python
{%- endif %} {%- endif %}
{%- if cookiecutter.use_docker == "n" and cookiecutter.windows == "y" %} {%- if cookiecutter.use_docker == "n" and cookiecutter.windows == "y" %}
hiredis==2.3.2 # https://github.com/redis/hiredis-py hiredis==3.0.0 # https://github.com/redis/hiredis-py
{%- endif %} {%- endif %}
# Django # Django
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
{%- if cookiecutter.cloud_provider == 'AWS' %} {%- if cookiecutter.cloud_provider == 'AWS' %}
django-storages[s3]==1.14.3 # https://github.com/jschneier/django-storages django-storages[s3]==1.14.4 # https://github.com/jschneier/django-storages
{%- elif cookiecutter.cloud_provider == 'GCP' %} {%- elif cookiecutter.cloud_provider == 'GCP' %}
django-storages[google]==1.14.3 # https://github.com/jschneier/django-storages django-storages[google]==1.14.4 # https://github.com/jschneier/django-storages
{%- elif cookiecutter.cloud_provider == 'Azure' %} {%- elif cookiecutter.cloud_provider == 'Azure' %}
django-storages[azure]==1.14.3 # https://github.com/jschneier/django-storages django-storages[azure]==1.14.4 # https://github.com/jschneier/django-storages
{%- endif %} {%- endif %}
{%- if cookiecutter.mail_service == 'Mailgun' %} {%- if cookiecutter.mail_service == 'Mailgun' %}
django-anymail[mailgun]==10.3 # https://github.com/anymail/django-anymail django-anymail[mailgun]==11.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Amazon SES' %} {%- elif cookiecutter.mail_service == 'Amazon SES' %}
django-anymail[amazon-ses]==10.3 # https://github.com/anymail/django-anymail django-anymail[amazon-ses]==11.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Mailjet' %} {%- elif cookiecutter.mail_service == 'Mailjet' %}
django-anymail[mailjet]==10.3 # https://github.com/anymail/django-anymail django-anymail[mailjet]==11.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Mandrill' %} {%- elif cookiecutter.mail_service == 'Mandrill' %}
django-anymail[mandrill]==10.3 # https://github.com/anymail/django-anymail django-anymail[mandrill]==11.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Postmark' %} {%- elif cookiecutter.mail_service == 'Postmark' %}
django-anymail[postmark]==10.3 # https://github.com/anymail/django-anymail django-anymail[postmark]==11.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Sendgrid' %} {%- elif cookiecutter.mail_service == 'Sendgrid' %}
django-anymail[sendgrid]==10.3 # https://github.com/anymail/django-anymail django-anymail[sendgrid]==11.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'SendinBlue' %} {%- elif cookiecutter.mail_service == 'Brevo' %}
django-anymail[sendinblue]==10.3 # https://github.com/anymail/django-anymail django-anymail[brevo]==11.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'SparkPost' %} {%- elif cookiecutter.mail_service == 'SparkPost' %}
django-anymail[sparkpost]==10.3 # https://github.com/anymail/django-anymail django-anymail[sparkpost]==11.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Other SMTP' %} {%- elif cookiecutter.mail_service == 'Other SMTP' %}
django-anymail==10.3 # https://github.com/anymail/django-anymail django-anymail==11.1 # https://github.com/anymail/django-anymail
{%- endif %} {%- endif %}

View File

@ -1 +1 @@
python-3.12.3 python-3.12.5

View File

@ -9,6 +9,6 @@ def _media_storage(settings, tmpdir) -> None:
settings.MEDIA_ROOT = tmpdir.strpath settings.MEDIA_ROOT = tmpdir.strpath
@pytest.fixture() @pytest.fixture
def user(db) -> User: def user(db) -> User:
return UserFactory() return UserFactory()

View File

@ -24,6 +24,8 @@
{% endif %} {% endif %}
{% block content %} {% block content %}
{% endblock content %} {% endblock content %}
{% block extra_body %}
{% endblock extra_body %}
</div> </div>
</div> </div>
{% endblock body %}{% endraw %} {% endblock body %}{% endraw %}

View File

@ -56,7 +56,7 @@ class TestUserAdmin:
response = admin_client.get(url) response = admin_client.get(url)
assert response.status_code == HTTPStatus.OK assert response.status_code == HTTPStatus.OK
@pytest.fixture() @pytest.fixture
def _force_allauth(self, settings): def _force_allauth(self, settings):
settings.DJANGO_ADMIN_FORCE_ALLAUTH = True settings.DJANGO_ADMIN_FORCE_ALLAUTH = True
# Reload the admin module to apply the setting change # Reload the admin module to apply the setting change
@ -65,7 +65,7 @@ class TestUserAdmin:
with contextlib.suppress(admin.sites.AlreadyRegistered): # type: ignore[attr-defined] with contextlib.suppress(admin.sites.AlreadyRegistered): # type: ignore[attr-defined]
reload(users_admin) reload(users_admin)
@pytest.mark.django_db() @pytest.mark.django_db
@pytest.mark.usefixtures("_force_allauth") @pytest.mark.usefixtures("_force_allauth")
def test_allauth_login(self, rf, settings): def test_allauth_login(self, rf, settings):
request = rf.get("/fake-url") request = rf.get("/fake-url")

View File

@ -6,7 +6,7 @@ from {{ cookiecutter.project_slug }}.users.models import User
class TestUserViewSet: class TestUserViewSet:
@pytest.fixture() @pytest.fixture
def api_rf(self) -> APIRequestFactory: def api_rf(self) -> APIRequestFactory:
return APIRequestFactory() return APIRequestFactory()

View File

@ -6,7 +6,7 @@ from django.core.management import call_command
from {{ cookiecutter.project_slug }}.users.models import User from {{ cookiecutter.project_slug }}.users.models import User
@pytest.mark.django_db() @pytest.mark.django_db
class TestUserManager: class TestUserManager:
def test_create_user(self): def test_create_user(self):
user = User.objects.create_user( user = User.objects.create_user(
@ -37,7 +37,7 @@ class TestUserManager:
assert user.username is None assert user.username is None
@pytest.mark.django_db() @pytest.mark.django_db
def test_createsuperuser_command(): def test_createsuperuser_command():
"""Ensure createsuperuser command works with our custom manager.""" """Ensure createsuperuser command works with our custom manager."""
out = StringIO() out = StringIO()

View File

@ -10,7 +10,7 @@ def test_swagger_accessible_by_admin(admin_client):
assert response.status_code == HTTPStatus.OK assert response.status_code == HTTPStatus.OK
@pytest.mark.django_db() @pytest.mark.django_db
def test_swagger_ui_not_accessible_by_normal_user(client): def test_swagger_ui_not_accessible_by_normal_user(client):
url = reverse("api-docs") url = reverse("api-docs")
response = client.get(url) response = client.get(url)

View File

@ -1,5 +1,6 @@
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin from django.contrib.messages.views import SuccessMessageMixin
from django.db.models import QuerySet
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.views.generic import DetailView from django.views.generic import DetailView
@ -28,12 +29,12 @@ class UserUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
fields = ["name"] fields = ["name"]
success_message = _("Information successfully updated") success_message = _("Information successfully updated")
def get_success_url(self): def get_success_url(self) -> str:
# for mypy to know that the user is authenticated assert self.request.user.is_authenticated # type guard
assert self.request.user.is_authenticated
return self.request.user.get_absolute_url() return self.request.user.get_absolute_url()
def get_object(self): def get_object(self, queryset: QuerySet | None=None) -> User:
assert self.request.user.is_authenticated # type guard
return self.request.user return self.request.user
@ -43,7 +44,7 @@ user_update_view = UserUpdateView.as_view()
class UserRedirectView(LoginRequiredMixin, RedirectView): class UserRedirectView(LoginRequiredMixin, RedirectView):
permanent = False permanent = False
def get_redirect_url(self): def get_redirect_url(self) -> str:
{%- if cookiecutter.username_type == "email" %} {%- if cookiecutter.username_type == "email" %}
return reverse("users:detail", kwargs={"pk": self.request.user.pk}) return reverse("users:detail", kwargs={"pk": self.request.user.pk})
{%- else %} {%- else %}