Merge branch 'main' of https://github.com/cookiecutter/cookiecutter-django into cookiecutter-master

# Conflicts:
#	{{cookiecutter.project_slug}}/requirements/local.txt
This commit is contained in:
Alejandro Franco 2025-09-01 18:39:59 -06:00
commit ed2d13c351
39 changed files with 554 additions and 186 deletions

View File

@ -1,4 +0,0 @@
[flake8]
exclude = docs
max-line-length = 119
extend-ignore = E203

View File

@ -13,7 +13,6 @@ labels: bug
<!-- To assist you best, please include commands that you've run, options you've selected and any relevant logs --> <!-- To assist you best, please include commands that you've run, options you've selected and any relevant logs -->
- Host system configuration: - Host system configuration:
- Version of cookiecutter CLI (get it with `cookiecutter --version`): - Version of cookiecutter CLI (get it with `cookiecutter --version`):
- OS name and version: - OS name and version:

View File

@ -1728,5 +1728,30 @@
"name": "Dominique Plante", "name": "Dominique Plante",
"github_login": "dominiqueplante", "github_login": "dominiqueplante",
"twitter_username": "" "twitter_username": ""
},
{
"name": "Lucas Klasa",
"github_login": "lucaskbr",
"twitter_username": ""
},
{
"name": "DevForsure",
"github_login": "DevForsure",
"twitter_username": ""
},
{
"name": "Vincent Leduc",
"github_login": "leducvin",
"twitter_username": ""
},
{
"name": "Martín Blech",
"github_login": "martinblech",
"twitter_username": ""
},
{
"name": "jlitrell",
"github_login": "jlitrell",
"twitter_username": ""
} }
] ]

View File

@ -14,7 +14,7 @@ permissions:
jobs: jobs:
run: run:
if: ${{ github.actor == 'pyup-bot' }} if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' && (github.event.pull_request.user.login == 'pyup-bot' || github.event.pull_request.user.login == 'dependabot[bot]') }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
GH_PAT: ${{ secrets.GH_PAT }} GH_PAT: ${{ secrets.GH_PAT }}
@ -31,14 +31,14 @@ jobs:
name: "${{ matrix.job.name }} versions" name: "${{ matrix.job.name }} versions"
steps: steps:
- name: Checkout with token - name: Checkout with token
uses: actions/checkout@v4 uses: actions/checkout@v5
if: ${{ env.GH_PAT != '' }} if: ${{ env.GH_PAT != '' }}
with: with:
token: ${{ env.GH_PAT }} token: ${{ env.GH_PAT }}
ref: ${{ github.head_ref }} ref: ${{ github.head_ref }}
- name: Checkout without token - name: Checkout without token
uses: actions/checkout@v4 uses: actions/checkout@v5
if: ${{ env.GH_PAT == '' }} if: ${{ env.GH_PAT == '' }}
with: with:
ref: ${{ github.head_ref }} ref: ${{ github.head_ref }}

View File

@ -2,7 +2,7 @@ name: CI
on: on:
push: push:
branches: ["master", "main"] branches: ["main"]
pull_request: pull_request:
concurrency: concurrency:
@ -22,7 +22,7 @@ jobs:
name: "pytest ${{ matrix.os }}" name: "pytest ${{ matrix.os }}"
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v5
- name: Install uv - name: Install uv
uses: astral-sh/setup-uv@v6 uses: astral-sh/setup-uv@v6
- name: Install dependencies - name: Install dependencies
@ -51,7 +51,7 @@ jobs:
COMPOSE_DOCKER_CLI_BUILD: 1 COMPOSE_DOCKER_CLI_BUILD: 1
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v5
- name: Install uv - name: Install uv
uses: astral-sh/setup-uv@v6 uses: astral-sh/setup-uv@v6
- name: Install dependencies - name: Install dependencies
@ -93,7 +93,7 @@ jobs:
DATABASE_URL: "postgres://postgres:postgres@localhost:5432/postgres" DATABASE_URL: "postgres://postgres:postgres@localhost:5432/postgres"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v5
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
with: with:
python-version: "3.12" python-version: "3.12"
@ -103,6 +103,6 @@ jobs:
run: uv sync run: uv sync
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version: "22.14" node-version: "24.7"
- name: Bare Metal ${{ matrix.script.name }} - name: Bare Metal ${{ matrix.script.name }}
run: sh tests/test_bare.sh ${{ matrix.script.args }} run: sh tests/test_bare.sh ${{ matrix.script.args }}

View File

@ -17,13 +17,13 @@ jobs:
GH_PAT: ${{ secrets.GH_PAT }} GH_PAT: ${{ secrets.GH_PAT }}
steps: steps:
- name: Checkout with token - name: Checkout with token
uses: actions/checkout@v4 uses: actions/checkout@v5
if: ${{ env.GH_PAT != '' }} if: ${{ env.GH_PAT != '' }}
with: with:
token: ${{ env.GH_PAT }} token: ${{ env.GH_PAT }}
- name: Checkout without token - name: Checkout without token
uses: actions/checkout@v4 uses: actions/checkout@v5
if: ${{ env.GH_PAT == '' }} if: ${{ env.GH_PAT == '' }}
- uses: astral-sh/setup-uv@v6 - uses: astral-sh/setup-uv@v6

View File

@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v5
- name: Install uv - name: Install uv
uses: astral-sh/setup-uv@v6 uses: astral-sh/setup-uv@v6
- name: Create Django Major Issue - name: Create Django Major Issue

View File

@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v5
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
with: with:
python-version: "3.12" python-version: "3.12"

View File

@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v5
- name: Install uv - name: Install uv
uses: astral-sh/setup-uv@v6 uses: astral-sh/setup-uv@v6
- name: Set git details - name: Set git details

View File

@ -3,7 +3,7 @@ name: Update Contributors
on: on:
push: push:
branches: branches:
- master - main
permissions: permissions:
contents: read contents: read
@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v5
- name: Install uv - name: Install uv
uses: astral-sh/setup-uv@v6 uses: astral-sh/setup-uv@v6
- name: Update list - name: Update list

View File

@ -7,7 +7,7 @@ default_language_version:
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0 rev: v6.0.0
hooks: hooks:
- id: trailing-whitespace - id: trailing-whitespace
- id: end-of-file-fixer - id: end-of-file-fixer
@ -26,27 +26,12 @@ repos:
- id: prettier - id: prettier
args: ["--tab-width", "2"] args: ["--tab-width", "2"]
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v3.20.0 rev: v0.12.11
hooks: hooks:
- id: pyupgrade - id: ruff
args: [--py312-plus] args: [--fix, --exit-non-zero-on-fix]
exclude: hooks/ - id: ruff-format
- repo: https://github.com/psf/black
rev: 25.1.0
hooks:
- id: black
- repo: https://github.com/PyCQA/isort
rev: 6.0.1
hooks:
- id: isort
- repo: https://github.com/PyCQA/flake8
rev: 7.3.0
hooks:
- id: flake8
- repo: https://github.com/tox-dev/pyproject-fmt - repo: https://github.com/tox-dev/pyproject-fmt
rev: "v2.6.0" rev: "v2.6.0"

View File

@ -3,6 +3,280 @@ All enhancements and patches to Cookiecutter Django will be documented in this f
<!-- GENERATOR_PLACEHOLDER --> <!-- GENERATOR_PLACEHOLDER -->
## 2025.08.31
### Updated
- Update coverage to 7.10.6 ([#5999](https://github.com/cookiecutter/cookiecutter-django/pull/5999))
## 2025.08.29
### Updated
- Bump node from 24.6-bookworm-slim to 24.7-bookworm-slim in /{{cookiecutter.project_slug}}/compose/local/node ([#5997](https://github.com/cookiecutter/cookiecutter-django/pull/5997))
- Update ruff to 0.12.11 ([#5998](https://github.com/cookiecutter/cookiecutter-django/pull/5998))
## 2025.08.28
### Updated
- Update django-allauth to 65.11.1 ([#5992](https://github.com/cookiecutter/cookiecutter-django/pull/5992))
- Auto-update pre-commit hooks ([#5993](https://github.com/cookiecutter/cookiecutter-django/pull/5993))
## 2025.08.27
### Updated
- Update django-upgrade pre-commit hook ([#5991](https://github.com/cookiecutter/cookiecutter-django/pull/5991))
## 2025.08.26
### Updated
- Update sentry-sdk to 2.35.1 ([#5988](https://github.com/cookiecutter/cookiecutter-django/pull/5988))
- Update sphinx-autobuild to 2025.8.25 ([#5989](https://github.com/cookiecutter/cookiecutter-django/pull/5989))
## 2025.08.25
### Updated
- Update collectfasta to 3.3.1 ([#5987](https://github.com/cookiecutter/cookiecutter-django/pull/5987))
- Update coverage to 7.10.5 ([#5986](https://github.com/cookiecutter/cookiecutter-django/pull/5986))
- Update pytest-sugar to 1.1.1 ([#5984](https://github.com/cookiecutter/cookiecutter-django/pull/5984))
## 2025.08.21
### Updated
- Update ruff to 0.12.10 ([#5983](https://github.com/cookiecutter/cookiecutter-django/pull/5983))
## 2025.08.18
### Updated
- Bump node from 24.5 to 24.6 ([#5981](https://github.com/cookiecutter/cookiecutter-django/pull/5981))
- Update coverage to 7.10.4 ([#5980](https://github.com/cookiecutter/cookiecutter-django/pull/5980))
- Update pytest-sugar to 1.1.0 ([#5979](https://github.com/cookiecutter/cookiecutter-django/pull/5979))
## 2025.08.15
### Updated
- Update django-allauth to 65.11.0 ([#5977](https://github.com/cookiecutter/cookiecutter-django/pull/5977))
- Update sentry-sdk to 2.35.0 ([#5976](https://github.com/cookiecutter/cookiecutter-django/pull/5976))
## 2025.08.14
### Updated
- Update ruff to 0.12.9 ([#5975](https://github.com/cookiecutter/cookiecutter-django/pull/5975))
## 2025.08.13
### Fixed
- Fix imagemin corruption with Gulp ([#5974](https://github.com/cookiecutter/cookiecutter-django/pull/5974))
## 2025.08.12
### Updated
- Update coverage to 7.10.3 ([#5972](https://github.com/cookiecutter/cookiecutter-django/pull/5972))
## 2025.08.10
### Updated
- Update pre-commit to 4.3.0 ([#5971](https://github.com/cookiecutter/cookiecutter-django/pull/5971))
- Auto-update pre-commit hooks ([#5970](https://github.com/cookiecutter/cookiecutter-django/pull/5970))
## 2025.08.08
### Changed
- Remove `project.css` when a bundler is used ([#5874](https://github.com/cookiecutter/cookiecutter-django/pull/5874))
### Updated
- Update redis to 6.4.0 ([#5968](https://github.com/cookiecutter/cookiecutter-django/pull/5968))
- Update ruff to 0.12.8 ([#5969](https://github.com/cookiecutter/cookiecutter-django/pull/5969))
## 2025.08.07
### Updated
- Update djangorestframework to 3.16.1 ([#5966](https://github.com/cookiecutter/cookiecutter-django/pull/5966))
## 2025.08.06
### Updated
- Update coverage to 7.10.2 ([#5964](https://github.com/cookiecutter/cookiecutter-django/pull/5964))
- Update redis to 6.3.0 ([#5963](https://github.com/cookiecutter/cookiecutter-django/pull/5963))
## 2025.08.05
### Changed
- Rename `master` branch to `main` ([#5961](https://github.com/cookiecutter/cookiecutter-django/pull/5961))
### Updated
- Bump node from 22.14 to 24.5 in local Docker image ([#5960](https://github.com/cookiecutter/cookiecutter-django/pull/5960))
## 2025.08.01
### Updated
- Update django-debug-toolbar to 6.0.0 ([#5945](https://github.com/cookiecutter/cookiecutter-django/pull/5945))
- Bump amazon/aws-cli from 2.27.12 to 2.28.0 ([#5957](https://github.com/cookiecutter/cookiecutter-django/pull/5957))
- Update mypy to 1.17.1 ([#5956](https://github.com/cookiecutter/cookiecutter-django/pull/5956))
## 2025.07.30
### Changed
- docs: remove `$` from shell command examples for easier copy-pasting ([#5948](https://github.com/cookiecutter/cookiecutter-django/pull/5948))
### Updated
- Update sentry-sdk to 2.34.1 ([#5955](https://github.com/cookiecutter/cookiecutter-django/pull/5955))
- Update ruff to 0.12.7 ([#5952](https://github.com/cookiecutter/cookiecutter-django/pull/5952))
## 2025.07.27
### Updated
- Update coverage to 7.10.1 ([#5947](https://github.com/cookiecutter/cookiecutter-django/pull/5947))
## 2025.07.25
### Updated
- Update django-anymail to 13.0.1 ([#5946](https://github.com/cookiecutter/cookiecutter-django/pull/5946))
## 2025.07.24
### Updated
- Update coverage to 7.10.0 ([#5944](https://github.com/cookiecutter/cookiecutter-django/pull/5944))
- Update ruff to 0.12.5 ([#5943](https://github.com/cookiecutter/cookiecutter-django/pull/5943))
- Bump traefik from 3.4.4 to 3.5.0 ([#5942](https://github.com/cookiecutter/cookiecutter-django/pull/5942))
## 2025.07.22
### Updated
- Update sentry-sdk to 2.33.2 ([#5941](https://github.com/cookiecutter/cookiecutter-django/pull/5941))
## 2025.07.21
### Updated
- Update sentry-sdk to 2.33.1 ([#5940](https://github.com/cookiecutter/cookiecutter-django/pull/5940))
## 2025.07.18
### Updated
- Update mypy to 1.17.0 ([#5937](https://github.com/cookiecutter/cookiecutter-django/pull/5937))
- Update django-stubs to 5.2.2 ([#5936](https://github.com/cookiecutter/cookiecutter-django/pull/5936))
## 2025.07.17
### Updated
- Update ruff to 0.12.4 ([#5935](https://github.com/cookiecutter/cookiecutter-django/pull/5935))
## 2025.07.16
### Updated
- Update sentry-sdk to 2.33.0 ([#5933](https://github.com/cookiecutter/cookiecutter-django/pull/5933))
## 2025.07.15
### Updated
- Update mypy to 1.16.1 ([#5901](https://github.com/cookiecutter/cookiecutter-django/pull/5901))
- Bump traefik from 3.4.3 to 3.4.4 ([#5930](https://github.com/cookiecutter/cookiecutter-django/pull/5930))
## 2025.07.14
### Changed
- Fix howto docker command ([#5929](https://github.com/cookiecutter/cookiecutter-django/pull/5929))
## 2025.07.11
### Updated
- Update ruff to 0.12.3 ([#5928](https://github.com/cookiecutter/cookiecutter-django/pull/5928))
- Update django-allauth to 65.10.0 ([#5927](https://github.com/cookiecutter/cookiecutter-django/pull/5927))
## 2025.07.05
### Updated
- Update coverage to 7.9.2 ([#5925](https://github.com/cookiecutter/cookiecutter-django/pull/5925))
## 2025.07.04
### Updated
- Update ruff to 0.12.2 ([#5923](https://github.com/cookiecutter/cookiecutter-django/pull/5923))
## 2025.07.02 ## 2025.07.02

View File

@ -14,7 +14,7 @@ Always happy to get issues identified and pull requests!
2. Clone your fork 2. Clone your fork
3. Create a branch for your changes 3. Create a branch for your changes
This last step is very important, don't start developing from master, it'll cause pain if you need to send another change later. This last step is very important, don't start developing from main, it'll cause pain if you need to send another change later.
## Testing ## Testing

View File

@ -768,6 +768,13 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>DevForsure</td>
<td>
<a href="https://github.com/DevForsure">DevForsure</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>Diane Chen</td> <td>Diane Chen</td>
<td> <td>
@ -1265,6 +1272,13 @@ Listed in alphabetical order.
</td> </td>
<td>afrowave</td> <td>afrowave</td>
</tr> </tr>
<tr>
<td>jlitrell</td>
<td>
<a href="https://github.com/jlitrell">jlitrell</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>John</td> <td>John</td>
<td> <td>
@ -1510,6 +1524,13 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>Lucas Klasa</td>
<td>
<a href="https://github.com/lucaskbr">lucaskbr</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>Luis Nell</td> <td>Luis Nell</td>
<td> <td>
@ -1594,6 +1615,13 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>Martín Blech</td>
<td>
<a href="https://github.com/martinblech">martinblech</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>masavini</td> <td>masavini</td>
<td> <td>
@ -2336,6 +2364,13 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>Vincent Leduc</td>
<td>
<a href="https://github.com/leducvin">leducvin</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>Vitaly Babiy</td> <td>Vitaly Babiy</td>
<td> <td>

View File

@ -1,8 +1,8 @@
# Cookiecutter Django # Cookiecutter Django
[![Build Status](https://img.shields.io/github/actions/workflow/status/cookiecutter/cookiecutter-django/ci.yml?branch=master)](https://github.com/cookiecutter/cookiecutter-django/actions/workflows/ci.yml?query=branch%3Amaster) [![Build Status](https://img.shields.io/github/actions/workflow/status/cookiecutter/cookiecutter-django/ci.yml?branch=main)](https://github.com/cookiecutter/cookiecutter-django/actions/workflows/ci.yml?query=branch%3Amain)
[![Documentation Status](https://readthedocs.org/projects/cookiecutter-django/badge/?version=latest)](https://cookiecutter-django.readthedocs.io/en/latest/?badge=latest) [![Documentation Status](https://readthedocs.org/projects/cookiecutter-django/badge/?version=latest)](https://cookiecutter-django.readthedocs.io/en/latest/?badge=latest)
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/cookiecutter/cookiecutter-django/master.svg)](https://results.pre-commit.ci/latest/github/cookiecutter/cookiecutter-django/master) [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/cookiecutter/cookiecutter-django/main.svg)](https://results.pre-commit.ci/latest/github/cookiecutter/cookiecutter-django/main)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
[![Updates](https://pyup.io/repos/github/cookiecutter/cookiecutter-django/shield.svg)](https://pyup.io/repos/github/cookiecutter/cookiecutter-django/) [![Updates](https://pyup.io/repos/github/cookiecutter/cookiecutter-django/shield.svg)](https://pyup.io/repos/github/cookiecutter/cookiecutter-django/)
@ -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://f004.backblazeb2.com/file/feldroycom/images/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-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!
@ -84,11 +84,11 @@ and then editing the results to include your name, email, and various configurat
First, get Cookiecutter. Trust me, it's awesome: First, get Cookiecutter. Trust me, it's awesome:
$ pip install "cookiecutter>=1.7.0" pip install "cookiecutter>=1.7.0"
Now run it against this repo: Now run it against this repo:
$ cookiecutter https://github.com/cookiecutter/cookiecutter-django cookiecutter https://github.com/cookiecutter/cookiecutter-django
You'll be prompted for some values. Provide them, then a Django project will be created for you. You'll be prompted for some values. Provide them, then a Django project will be created for you.
@ -171,16 +171,16 @@ Answer the prompts with your own desired [options](http://cookiecutter-django.re
Enter the project and take a look around: Enter the project and take a look around:
$ cd reddit/ cd reddit/
$ ls ls
Create a git repo and push it there: Create a git repo and push it there:
$ git init git init
$ git add . git add .
$ git commit -m "first awesome commit" git commit -m "first awesome commit"
$ git remote add origin git@github.com:pydanny/redditclone.git git remote add origin git@github.com:pydanny/redditclone.git
$ git push -u origin master git push -u origin main
Now take a look at your repo. Don't forget to carefully look at the generated README. Awesome, right? Now take a look at your repo. Don't forget to carefully look at the generated README. Awesome, right?

View File

@ -10,7 +10,7 @@ It is there to add a migration so you don't have to manually change the ``sites.
See `0003_set_site_domain_and_name.py`_. See `0003_set_site_domain_and_name.py`_.
.. _`0003_set_site_domain_and_name.py`: https://github.com/cookiecutter/cookiecutter-django/blob/master/%7B%7Bcookiecutter.project_slug%7D%7D/%7B%7Bcookiecutter.project_slug%7D%7D/contrib/sites/migrations/0003_set_site_domain_and_name.py .. _`0003_set_site_domain_and_name.py`: https://github.com/cookiecutter/cookiecutter-django/blob/main/%7B%7Bcookiecutter.project_slug%7D%7D/%7B%7Bcookiecutter.project_slug%7D%7D/contrib/sites/migrations/0003_set_site_domain_and_name.py
Why aren't you using just one configuration file (12-Factor App) Why aren't you using just one configuration file (12-Factor App)

View File

@ -96,9 +96,9 @@ With that in mind, when merging changes, it's a good idea to set the labels and
`update-contributors.yml` `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. Runs on each push to main 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 #### 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 a pull request from a new contributor, and merge another one right after, the push to main 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. - If you merge more than 5 pull requests in a row like this, the new contributor might fail to be added.

0
hooks/__init__.py Normal file
View File

View File

@ -1,3 +1,4 @@
# ruff: noqa: PLR0133
import json import json
import random import random
import shutil import shutil
@ -6,7 +7,7 @@ from pathlib import Path
try: try:
# Inspired by # Inspired by
# https://github.com/django/django/blob/master/django/utils/crypto.py # https://github.com/django/django/blob/main/django/utils/crypto.py
random = random.SystemRandom() random = random.SystemRandom()
using_sysrandom = True using_sysrandom = True
except NotImplementedError: except NotImplementedError:
@ -79,7 +80,7 @@ def remove_heroku_files():
file_names = ["Procfile", "requirements.txt"] file_names = ["Procfile", "requirements.txt"]
for file_name in file_names: for file_name in file_names:
if file_name == "requirements.txt" and "{{ cookiecutter.ci_tool }}".lower() == "travis": if file_name == "requirements.txt" and "{{ cookiecutter.ci_tool }}".lower() == "travis":
# don't remove the file if we are using travisci but not using heroku # Don't remove the file if we are using Travis CI but not using Heroku
continue continue
Path(file_name).unlink() Path(file_name).unlink()
shutil.rmtree("bin") shutil.rmtree("bin")
@ -106,6 +107,12 @@ def remove_vendors_js():
vendors_js_path.unlink() vendors_js_path.unlink()
def remove_project_css():
project_css_path = Path("{{ cookiecutter.project_slug }}", "static", "css", "project.css")
if project_css_path.exists():
project_css_path.unlink()
def remove_packagejson_file(): def remove_packagejson_file():
file_names = ["package.json"] file_names = ["package.json"]
for file_name in file_names: for file_name in file_names:
@ -179,7 +186,7 @@ def handle_js_runner(choice, use_docker, use_async):
"dev": "concurrently npm:dev:*", "dev": "concurrently npm:dev:*",
"dev:webpack": "webpack serve --config webpack/dev.config.js", "dev:webpack": "webpack serve --config webpack/dev.config.js",
"dev:django": dev_django_cmd, "dev:django": dev_django_cmd,
} },
) )
else: else:
remove_dev_deps.append("concurrently") remove_dev_deps.append("concurrently")
@ -239,7 +246,7 @@ def remove_dotdrone_file():
Path(".drone.yml").unlink() Path(".drone.yml").unlink()
def generate_random_string(length, using_digits=False, using_ascii_letters=False, using_punctuation=False): def generate_random_string(length, using_digits=False, using_ascii_letters=False, using_punctuation=False): # noqa: FBT002
""" """
Example: Example:
opting out for 50 symbol-long, [a-z][A-Z][0-9] string opting out for 50 symbol-long, [a-z][A-Z][0-9] string
@ -268,7 +275,7 @@ def set_flag(file_path: Path, flag, value=None, formatted=None, *args, **kwargs)
if random_string is None: if random_string is None:
print( print(
"We couldn't find a secure pseudo-random number generator on your " "We couldn't find a secure pseudo-random number generator on your "
"system. Please, make sure to manually {} later.".format(flag) f"system. Please, make sure to manually {flag} later.",
) )
random_string = flag random_string = flag
if formatted is not None: if formatted is not None:
@ -285,18 +292,17 @@ def set_flag(file_path: Path, flag, value=None, formatted=None, *args, **kwargs)
def set_django_secret_key(file_path: Path): def set_django_secret_key(file_path: Path):
django_secret_key = set_flag( return set_flag(
file_path, file_path,
"!!!SET DJANGO_SECRET_KEY!!!", "!!!SET DJANGO_SECRET_KEY!!!",
length=64, length=64,
using_digits=True, using_digits=True,
using_ascii_letters=True, using_ascii_letters=True,
) )
return django_secret_key
def set_django_admin_url(file_path: Path): def set_django_admin_url(file_path: Path):
django_admin_url = set_flag( return set_flag(
file_path, file_path,
"!!!SET DJANGO_ADMIN_URL!!!", "!!!SET DJANGO_ADMIN_URL!!!",
formatted="{}/", formatted="{}/",
@ -304,24 +310,22 @@ def set_django_admin_url(file_path: Path):
using_digits=True, using_digits=True,
using_ascii_letters=True, using_ascii_letters=True,
) )
return django_admin_url
def generate_random_user(): def generate_random_user():
return generate_random_string(length=32, using_ascii_letters=True) return generate_random_string(length=32, using_ascii_letters=True)
def generate_postgres_user(debug=False): def generate_postgres_user(debug=False): # noqa: FBT002
return DEBUG_VALUE if debug else generate_random_user() return DEBUG_VALUE if debug else generate_random_user()
def set_postgres_user(file_path, value): def set_postgres_user(file_path, value):
postgres_user = set_flag(file_path, "!!!SET POSTGRES_USER!!!", value=value) return set_flag(file_path, "!!!SET POSTGRES_USER!!!", value=value)
return postgres_user
def set_postgres_password(file_path, value=None): def set_postgres_password(file_path, value=None):
postgres_password = set_flag( return set_flag(
file_path, file_path,
"!!!SET POSTGRES_PASSWORD!!!", "!!!SET POSTGRES_PASSWORD!!!",
value=value, value=value,
@ -329,16 +333,14 @@ def set_postgres_password(file_path, value=None):
using_digits=True, using_digits=True,
using_ascii_letters=True, using_ascii_letters=True,
) )
return postgres_password
def set_celery_flower_user(file_path, value): def set_celery_flower_user(file_path, value):
celery_flower_user = set_flag(file_path, "!!!SET CELERY_FLOWER_USER!!!", value=value) return set_flag(file_path, "!!!SET CELERY_FLOWER_USER!!!", value=value)
return celery_flower_user
def set_celery_flower_password(file_path, value=None): def set_celery_flower_password(file_path, value=None):
celery_flower_password = set_flag( return set_flag(
file_path, file_path,
"!!!SET CELERY_FLOWER_PASSWORD!!!", "!!!SET CELERY_FLOWER_PASSWORD!!!",
value=value, value=value,
@ -346,7 +348,6 @@ def set_celery_flower_password(file_path, value=None):
using_digits=True, using_digits=True,
using_ascii_letters=True, using_ascii_letters=True,
) )
return celery_flower_password
def append_to_gitignore_file(ignored_line): def append_to_gitignore_file(ignored_line):
@ -355,7 +356,7 @@ def append_to_gitignore_file(ignored_line):
gitignore_file.write("\n") gitignore_file.write("\n")
def set_flags_in_envs(postgres_user, celery_flower_user, debug=False): def set_flags_in_envs(postgres_user, celery_flower_user, debug=False): # noqa: FBT002
local_django_envs_path = Path(".envs", ".local", ".django") local_django_envs_path = Path(".envs", ".local", ".django")
production_django_envs_path = Path(".envs", ".production", ".django") production_django_envs_path = Path(".envs", ".production", ".django")
local_postgres_envs_path = Path(".envs", ".local", ".postgres") local_postgres_envs_path = Path(".envs", ".local", ".postgres")
@ -405,7 +406,7 @@ def remove_drf_starter_files():
shutil.rmtree(Path("{{cookiecutter.project_slug}}", "users", "tests", "api")) shutil.rmtree(Path("{{cookiecutter.project_slug}}", "users", "tests", "api"))
def main(): def main(): # noqa: C901, PLR0912, PLR0915
debug = "{{ cookiecutter.debug }}".lower() == "y" debug = "{{ cookiecutter.debug }}".lower() == "y"
set_flags_in_envs( set_flags_in_envs(
@ -444,7 +445,7 @@ def main():
print( print(
INFO + ".env(s) are only utilized when Docker Compose and/or " INFO + ".env(s) are only utilized when Docker Compose and/or "
"Heroku support is enabled so keeping them does not make sense " "Heroku support is enabled so keeping them does not make sense "
"given your current setup." + TERMINATOR "given your current setup." + TERMINATOR,
) )
remove_envs_and_associated_files() remove_envs_and_associated_files()
else: else:
@ -462,6 +463,7 @@ def main():
if "{{ cookiecutter.use_docker }}".lower() == "y": if "{{ cookiecutter.use_docker }}".lower() == "y":
remove_node_dockerfile() remove_node_dockerfile()
else: else:
remove_project_css()
handle_js_runner( handle_js_runner(
"{{ cookiecutter.frontend_pipeline }}", "{{ cookiecutter.frontend_pipeline }}",
use_docker=("{{ cookiecutter.use_docker }}".lower() == "y"), use_docker=("{{ cookiecutter.use_docker }}".lower() == "y"),
@ -471,7 +473,7 @@ def main():
if "{{ cookiecutter.cloud_provider }}" == "None" and "{{ cookiecutter.use_docker }}".lower() == "n": if "{{ cookiecutter.cloud_provider }}" == "None" and "{{ cookiecutter.use_docker }}".lower() == "n":
print( print(
WARNING + "You chose to not use any cloud providers nor Docker, " WARNING + "You chose to not use any cloud providers nor Docker, "
"media files won't be served in production." + TERMINATOR "media files won't be served in production." + TERMINATOR,
) )
if "{{ cookiecutter.use_celery }}".lower() == "n": if "{{ cookiecutter.use_celery }}".lower() == "n":

View File

@ -1,3 +1,4 @@
# ruff: noqa: PLR0133
import sys import sys
TERMINATOR = "\x1b[0m" TERMINATOR = "\x1b[0m"
@ -16,9 +17,9 @@ SUCCESS = "\x1b[1;32m [SUCCESS]: "
project_slug = "{{ cookiecutter.project_slug }}" project_slug = "{{ cookiecutter.project_slug }}"
if hasattr(project_slug, "isidentifier"): if hasattr(project_slug, "isidentifier"):
assert project_slug.isidentifier(), "'{}' project slug is not a valid Python identifier.".format(project_slug) assert project_slug.isidentifier(), f"'{project_slug}' project slug is not a valid Python identifier."
assert project_slug == project_slug.lower(), "'{}' project slug should be all lowercase".format(project_slug) assert project_slug == project_slug.lower(), f"'{project_slug}' project slug should be all lowercase"
assert "\\" not in "{{ cookiecutter.author_name }}", "Don't include backslashes in author name." assert "\\" not in "{{ cookiecutter.author_name }}", "Don't include backslashes in author name."

View File

@ -1,6 +1,6 @@
[project] [project]
name = "cookiecutter-django" name = "cookiecutter-django"
version = "2025.07.02" version = "2025.08.31"
description = "A Cookiecutter template for creating production-ready Django projects quickly." description = "A Cookiecutter template for creating production-ready Django projects quickly."
readme = "README.md" readme = "README.md"
keywords = [ keywords = [
@ -43,7 +43,7 @@ dependencies = [
"pytest-xdist==3.6.1", "pytest-xdist==3.6.1",
"pyyaml==6.0.2", "pyyaml==6.0.2",
"requests==2.32.3", "requests==2.32.3",
"ruff==0.12.1", "ruff==0.12.11",
"sh==2.1; sys_platform!='win23'", "sh==2.1; sys_platform!='win23'",
"tox==4.23.2", "tox==4.23.2",
"tox-uv>=1.17", "tox-uv>=1.17",
@ -58,22 +58,83 @@ docs = [
"sphinx-rtd-theme>=3", "sphinx-rtd-theme>=3",
] ]
[tool.black] [tool.ruff]
target-version = "py39"
line-length = 119 line-length = 119
target-version = [ # Exclude the template content as most files aren't parseable
'py312', extend-exclude = [
"[{]{2}cookiecutter.project_slug[}]{2}/*",
"docs/*",
] ]
# ==== isort ==== lint.select = [
"A",
[tool.isort] # "ANN", # flake8-annotations: we should support this in the future but many errors atm
profile = "black" "ASYNC",
line_length = 119 "B",
known_first_party = [ "BLE",
"tests", "C4",
"scripts", "C90",
"hooks", "COM",
"DTZ",
"E",
"EM",
"ERA",
"EXE",
"F",
"FA",
"FBT",
"FLY",
"G",
"I",
"ICN",
"INP",
"INT",
"ISC",
"N",
"PD",
"PERF",
"PGH",
"PIE",
"PL",
"PT",
# "ARG", # Unused function argument
"PTH",
"PYI",
"Q",
"RET",
"RSE",
# "FURB",
# "LOG",
"RUF",
"S",
"SIM",
"SLF",
"SLOT",
"T10",
"TC",
"TID",
"TRY",
"UP",
"W",
"YTT",
] ]
lint.ignore = [
"EM101",
"RUF012", # Mutable class attributes should be annotated with `typing.ClassVar`
"S101", # Use of assert detected https://docs.astral.sh/ruff/rules/assert/
"SIM102", # sometimes it's better to nest
"TRY003", # Avoid specifying long messages outside the exception class
# Checks for uses of isinstance/issubclass that take a tuple of types for comparison.
# Deactivated because it can make the code slow: https://github.com/astral-sh/ruff/issues/7871
"UP038",
]
# The fixes in extend-unsafe-fixes will require
# provide the `--unsafe-fixes` flag when fixing.
lint.extend-unsafe-fixes = [
"UP038",
]
lint.isort.force-single-line = true
[tool.pyproject-fmt] [tool.pyproject-fmt]
keep_full_version = true keep_full_version = true

View File

@ -13,7 +13,9 @@ import os
import re import re
import sys import sys
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING, Any, NamedTuple from typing import TYPE_CHECKING
from typing import Any
from typing import NamedTuple
import requests import requests
from github import Github from github import Github
@ -59,7 +61,7 @@ class DjVersion(NamedTuple):
def get_package_info(package: str) -> dict: def get_package_info(package: str) -> dict:
"""Get package metadata using PyPI API.""" """Get package metadata using PyPI API."""
# "django" converts to "Django" on redirect # "django" converts to "Django" on redirect
r = requests.get(f"https://pypi.org/pypi/{package}/json", allow_redirects=True) r = requests.get(f"https://pypi.org/pypi/{package}/json", allow_redirects=True) # noqa: S113
if not r.ok: if not r.ok:
print(f"Couldn't find package: {package}") print(f"Couldn't find package: {package}")
sys.exit(1) sys.exit(1)
@ -214,9 +216,9 @@ class GitHubManager:
for classifier in package_info["info"]["classifiers"]: for classifier in package_info["info"]["classifiers"]:
# Usually in the form of "Framework :: Django :: 3.2" # Usually in the form of "Framework :: Django :: 3.2"
tokens = classifier.split(" ") tokens = classifier.split(" ")
if len(tokens) >= 5 and tokens[2].lower() == "django" and "." in tokens[4]: if len(tokens) >= 5 and tokens[2].lower() == "django" and "." in tokens[4]: # noqa: PLR2004
version = DjVersion.parse(tokens[4]) version = DjVersion.parse(tokens[4])
if len(version) == 2: if len(version) == 2: # noqa: PLR2004
supported_dj_versions.append(version) supported_dj_versions.append(version)
if supported_dj_versions: if supported_dj_versions:

View File

@ -1,12 +1,14 @@
from __future__ import annotations from __future__ import annotations
import subprocess import subprocess
import tomllib
from pathlib import Path from pathlib import Path
import tomllib
ROOT = Path(__file__).parent.parent ROOT = Path(__file__).parent.parent
TEMPLATED_ROOT = ROOT / "{{cookiecutter.project_slug}}" TEMPLATED_ROOT = ROOT / "{{cookiecutter.project_slug}}"
REQUIREMENTS_LOCAL_TXT = TEMPLATED_ROOT / "requirements" / "local.txt" REQUIREMENTS_LOCAL_TXT = TEMPLATED_ROOT / "requirements" / "local.txt"
TEMPLATE_PRE_COMMIT_CONFIG = ROOT / ".pre-commit-config.yaml"
PRE_COMMIT_CONFIG = TEMPLATED_ROOT / ".pre-commit-config.yaml" PRE_COMMIT_CONFIG = TEMPLATED_ROOT / ".pre-commit-config.yaml"
PYPROJECT_TOML = ROOT / "pyproject.toml" PYPROJECT_TOML = ROOT / "pyproject.toml"
@ -18,7 +20,7 @@ def main() -> None:
return return
update_ruff_version(old_version, new_version) update_ruff_version(old_version, new_version)
subprocess.run(["uv", "lock", "--no-upgrade"], cwd=ROOT) subprocess.run(["uv", "lock", "--no-upgrade"], cwd=ROOT, check=False) # noqa: S607
def get_requirements_txt_version() -> str: def get_requirements_txt_version() -> str:
@ -44,12 +46,13 @@ def update_ruff_version(old_version: str, new_version: str) -> None:
f"ruff=={new_version}", f"ruff=={new_version}",
) )
PYPROJECT_TOML.write_text(new_content) PYPROJECT_TOML.write_text(new_content)
# Update pre-commit config # Update pre-commit configs
new_content = PRE_COMMIT_CONFIG.read_text().replace( for config_file in [PRE_COMMIT_CONFIG, TEMPLATE_PRE_COMMIT_CONFIG]:
f"repo: https://github.com/astral-sh/ruff-pre-commit\n rev: v{old_version}", new_content = config_file.read_text().replace(
f"repo: https://github.com/astral-sh/ruff-pre-commit\n rev: v{new_version}", f"repo: https://github.com/astral-sh/ruff-pre-commit\n rev: v{old_version}",
) f"repo: https://github.com/astral-sh/ruff-pre-commit\n rev: v{new_version}",
PRE_COMMIT_CONFIG.write_text(new_content) )
config_file.write_text(new_content)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -23,7 +23,7 @@ def main() -> None:
Script entry point. Script entry point.
""" """
# Generate changelog for PRs merged yesterday # Generate changelog for PRs merged yesterday
merged_date = dt.date.today() - dt.timedelta(days=1) merged_date = dt.date.today() - dt.timedelta(days=1) # noqa: DTZ011
repo = Github(login_or_token=GITHUB_TOKEN).get_repo(GITHUB_REPO) repo = Github(login_or_token=GITHUB_TOKEN).get_repo(GITHUB_REPO)
merged_pulls = list(iter_pulls(repo, merged_date)) merged_pulls = list(iter_pulls(repo, merged_date))
print(f"Merged pull requests: {merged_pulls}") print(f"Merged pull requests: {merged_pulls}")
@ -54,7 +54,7 @@ def main() -> None:
# Run uv lock # Run uv lock
uv_lock_path = ROOT / "uv.lock" uv_lock_path = ROOT / "uv.lock"
subprocess.run(["uv", "lock", "--no-upgrade"], cwd=ROOT) subprocess.run(["uv", "lock", "--no-upgrade"], cwd=ROOT, check=False) # noqa: S607
# Commit changes, create tag and push # Commit changes, create tag and push
update_git_repo([changelog_path, setup_py_path, uv_lock_path], release) update_git_repo([changelog_path, setup_py_path, uv_lock_path], release)

View File

@ -1,4 +1,4 @@
import glob import glob # noqa: EXE002
import os import os
import re import re
import sys import sys
@ -206,18 +206,6 @@ def test_ruff_format_passes(cookies, context_override):
pytest.fail(e.stdout.decode()) pytest.fail(e.stdout.decode())
@auto_fixable
@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id)
def test_isort_passes(cookies, context_override):
"""Check whether generated project passes isort style."""
result = cookies.bake(extra_context=context_override)
try:
sh.isort(_cwd=str(result.project_path))
except sh.ErrorReturnCode as e:
pytest.fail(e.stdout.decode())
@auto_fixable @auto_fixable
@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id) @pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id)
def test_django_upgrade_passes(cookies, context_override): def test_django_upgrade_passes(cookies, context_override):
@ -226,7 +214,7 @@ def test_django_upgrade_passes(cookies, context_override):
python_files = [ python_files = [
file_path.removeprefix(f"{result.project_path}/") file_path.removeprefix(f"{result.project_path}/")
for file_path in glob.glob(str(result.project_path / "**" / "*.py"), recursive=True) for file_path in glob.glob(str(result.project_path / "**" / "*.py"), recursive=True) # noqa: PTH207
] ]
try: try:
sh.django_upgrade( sh.django_upgrade(

View File

@ -1,11 +1,7 @@
[tox] [tox]
skipsdist = true skipsdist = true
envlist = py312,black-template envlist = py312
[testenv] [testenv]
passenv = AUTOFIXABLE_STYLES passenv = AUTOFIXABLE_STYLES
commands = pytest -n auto {posargs:./tests} commands = pytest -n auto {posargs:./tests}
[testenv:black-template]
deps = black
commands = black --check hooks tests docs scripts

43
uv.lock
View File

@ -182,7 +182,7 @@ wheels = [
[[package]] [[package]]
name = "cookiecutter-django" name = "cookiecutter-django"
version = "2025.7.2" version = "2025.8.31"
source = { virtual = "." } source = { virtual = "." }
dependencies = [ dependencies = [
{ name = "binaryornot" }, { name = "binaryornot" },
@ -229,7 +229,7 @@ requires-dist = [
{ name = "pytest-xdist", specifier = "==3.6.1" }, { name = "pytest-xdist", specifier = "==3.6.1" },
{ name = "pyyaml", specifier = "==6.0.2" }, { name = "pyyaml", specifier = "==6.0.2" },
{ name = "requests", specifier = "==2.32.3" }, { name = "requests", specifier = "==2.32.3" },
{ name = "ruff", specifier = "==0.12.1" }, { name = "ruff", specifier = "==0.12.11" },
{ name = "sh", marker = "sys_platform != 'win23'", specifier = "==2.1" }, { name = "sh", marker = "sys_platform != 'win23'", specifier = "==2.1" },
{ name = "tox", specifier = "==4.23.2" }, { name = "tox", specifier = "==4.23.2" },
{ name = "tox-uv", specifier = ">=1.17" }, { name = "tox-uv", specifier = ">=1.17" },
@ -830,27 +830,28 @@ wheels = [
[[package]] [[package]]
name = "ruff" name = "ruff"
version = "0.12.1" version = "0.12.11"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/97/38/796a101608a90494440856ccfb52b1edae90de0b817e76bfade66b12d320/ruff-0.12.1.tar.gz", hash = "sha256:806bbc17f1104fd57451a98a58df35388ee3ab422e029e8f5cf30aa4af2c138c", size = 4413426 } sdist = { url = "https://files.pythonhosted.org/packages/de/55/16ab6a7d88d93001e1ae4c34cbdcfb376652d761799459ff27c1dc20f6fa/ruff-0.12.11.tar.gz", hash = "sha256:c6b09ae8426a65bbee5425b9d0b82796dbb07cb1af045743c79bfb163001165d", size = 5347103 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/06/bf/3dba52c1d12ab5e78d75bd78ad52fb85a6a1f29cc447c2423037b82bed0d/ruff-0.12.1-py3-none-linux_armv6l.whl", hash = "sha256:6013a46d865111e2edb71ad692fbb8262e6c172587a57c0669332a449384a36b", size = 10305649 }, { url = "https://files.pythonhosted.org/packages/d6/a2/3b3573e474de39a7a475f3fbaf36a25600bfeb238e1a90392799163b64a0/ruff-0.12.11-py3-none-linux_armv6l.whl", hash = "sha256:93fce71e1cac3a8bf9200e63a38ac5c078f3b6baebffb74ba5274fb2ab276065", size = 11979885 },
{ url = "https://files.pythonhosted.org/packages/8c/65/dab1ba90269bc8c81ce1d499a6517e28fe6f87b2119ec449257d0983cceb/ruff-0.12.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b3f75a19e03a4b0757d1412edb7f27cffb0c700365e9d6b60bc1b68d35bc89e0", size = 11120201 }, { url = "https://files.pythonhosted.org/packages/76/e4/235ad6d1785a2012d3ded2350fd9bc5c5af8c6f56820e696b0118dfe7d24/ruff-0.12.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8e33ac7b28c772440afa80cebb972ffd823621ded90404f29e5ab6d1e2d4b93", size = 12742364 },
{ url = "https://files.pythonhosted.org/packages/3f/3e/2d819ffda01defe857fa2dd4cba4d19109713df4034cc36f06bbf582d62a/ruff-0.12.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:9a256522893cb7e92bb1e1153283927f842dea2e48619c803243dccc8437b8be", size = 10466769 }, { url = "https://files.pythonhosted.org/packages/2c/0d/15b72c5fe6b1e402a543aa9d8960e0a7e19dfb079f5b0b424db48b7febab/ruff-0.12.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d69fb9d4937aa19adb2e9f058bc4fbfe986c2040acb1a4a9747734834eaa0bfd", size = 11920111 },
{ url = "https://files.pythonhosted.org/packages/63/37/bde4cf84dbd7821c8de56ec4ccc2816bce8125684f7b9e22fe4ad92364de/ruff-0.12.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:069052605fe74c765a5b4272eb89880e0ff7a31e6c0dbf8767203c1fbd31c7ff", size = 10660902 }, { url = "https://files.pythonhosted.org/packages/3e/c0/f66339d7893798ad3e17fa5a1e587d6fd9806f7c1c062b63f8b09dda6702/ruff-0.12.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:411954eca8464595077a93e580e2918d0a01a19317af0a72132283e28ae21bee", size = 12160060 },
{ url = "https://files.pythonhosted.org/packages/0e/3a/390782a9ed1358c95e78ccc745eed1a9d657a537e5c4c4812fce06c8d1a0/ruff-0.12.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a684f125a4fec2d5a6501a466be3841113ba6847827be4573fddf8308b83477d", size = 10167002 }, { url = "https://files.pythonhosted.org/packages/03/69/9870368326db26f20c946205fb2d0008988aea552dbaec35fbacbb46efaa/ruff-0.12.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a2c0a2e1a450f387bf2c6237c727dd22191ae8c00e448e0672d624b2bbd7fb0", size = 11799848 },
{ url = "https://files.pythonhosted.org/packages/6d/05/f2d4c965009634830e97ffe733201ec59e4addc5b1c0efa035645baa9e5f/ruff-0.12.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdecdef753bf1e95797593007569d8e1697a54fca843d78f6862f7dc279e23bd", size = 11751522 }, { url = "https://files.pythonhosted.org/packages/25/8c/dd2c7f990e9b3a8a55eee09d4e675027d31727ce33cdb29eab32d025bdc9/ruff-0.12.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ca4c3a7f937725fd2413c0e884b5248a19369ab9bdd850b5781348ba283f644", size = 13536288 },
{ url = "https://files.pythonhosted.org/packages/35/4e/4bfc519b5fcd462233f82fc20ef8b1e5ecce476c283b355af92c0935d5d9/ruff-0.12.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:70d52a058c0e7b88b602f575d23596e89bd7d8196437a4148381a3f73fcd5010", size = 12520264 }, { url = "https://files.pythonhosted.org/packages/7a/30/d5496fa09aba59b5e01ea76775a4c8897b13055884f56f1c35a4194c2297/ruff-0.12.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4d1df0098124006f6a66ecf3581a7f7e754c4df7644b2e6704cd7ca80ff95211", size = 14490633 },
{ url = "https://files.pythonhosted.org/packages/85/b2/7756a6925da236b3a31f234b4167397c3e5f91edb861028a631546bad719/ruff-0.12.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84d0a69d1e8d716dfeab22d8d5e7c786b73f2106429a933cee51d7b09f861d4e", size = 12133882 }, { url = "https://files.pythonhosted.org/packages/9b/2f/81f998180ad53445d403c386549d6946d0748e536d58fce5b5e173511183/ruff-0.12.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a8dd5f230efc99a24ace3b77e3555d3fbc0343aeed3fc84c8d89e75ab2ff793", size = 13888430 },
{ url = "https://files.pythonhosted.org/packages/dd/00/40da9c66d4a4d51291e619be6757fa65c91b92456ff4f01101593f3a1170/ruff-0.12.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6cc32e863adcf9e71690248607ccdf25252eeeab5193768e6873b901fd441fed", size = 11608941 }, { url = "https://files.pythonhosted.org/packages/87/71/23a0d1d5892a377478c61dbbcffe82a3476b050f38b5162171942a029ef3/ruff-0.12.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4dc75533039d0ed04cd33fb8ca9ac9620b99672fe7ff1533b6402206901c34ee", size = 12913133 },
{ url = "https://files.pythonhosted.org/packages/91/e7/f898391cc026a77fbe68dfea5940f8213622474cb848eb30215538a2dadf/ruff-0.12.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fd49a4619f90d5afc65cf42e07b6ae98bb454fd5029d03b306bd9e2273d44cc", size = 11602887 }, { url = "https://files.pythonhosted.org/packages/80/22/3c6cef96627f89b344c933781ed38329bfb87737aa438f15da95907cbfd5/ruff-0.12.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fc58f9266d62c6eccc75261a665f26b4ef64840887fc6cbc552ce5b29f96cc8", size = 13169082 },
{ url = "https://files.pythonhosted.org/packages/f6/02/0891872fc6aab8678084f4cf8826f85c5d2d24aa9114092139a38123f94b/ruff-0.12.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ed5af6aaaea20710e77698e2055b9ff9b3494891e1b24d26c07055459bb717e9", size = 10521742 }, { url = "https://files.pythonhosted.org/packages/05/b5/68b3ff96160d8b49e8dd10785ff3186be18fd650d356036a3770386e6c7f/ruff-0.12.11-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5a0113bd6eafd545146440225fe60b4e9489f59eb5f5f107acd715ba5f0b3d2f", size = 13139490 },
{ url = "https://files.pythonhosted.org/packages/2a/98/d6534322c74a7d47b0f33b036b2498ccac99d8d8c40edadb552c038cecf1/ruff-0.12.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:801d626de15e6bf988fbe7ce59b303a914ff9c616d5866f8c79eb5012720ae13", size = 10149909 }, { url = "https://files.pythonhosted.org/packages/59/b9/050a3278ecd558f74f7ee016fbdf10591d50119df8d5f5da45a22c6afafc/ruff-0.12.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0d737b4059d66295c3ea5720e6efc152623bb83fde5444209b69cd33a53e2000", size = 11958928 },
{ url = "https://files.pythonhosted.org/packages/34/5c/9b7ba8c19a31e2b6bd5e31aa1e65b533208a30512f118805371dbbbdf6a9/ruff-0.12.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2be9d32a147f98a1972c1e4df9a6956d612ca5f5578536814372113d09a27a6c", size = 11136005 }, { url = "https://files.pythonhosted.org/packages/f9/bc/93be37347db854806904a43b0493af8d6873472dfb4b4b8cbb27786eb651/ruff-0.12.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:916fc5defee32dbc1fc1650b576a8fed68f5e8256e2180d4d9855aea43d6aab2", size = 11764513 },
{ url = "https://files.pythonhosted.org/packages/dc/34/9bbefa4d0ff2c000e4e533f591499f6b834346025e11da97f4ded21cb23e/ruff-0.12.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:49b7ce354eed2a322fbaea80168c902de9504e6e174fd501e9447cad0232f9e6", size = 11648579 }, { url = "https://files.pythonhosted.org/packages/7a/a1/1471751e2015a81fd8e166cd311456c11df74c7e8769d4aabfbc7584c7ac/ruff-0.12.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c984f07d7adb42d3ded5be894fb4007f30f82c87559438b4879fe7aa08c62b39", size = 12745154 },
{ url = "https://files.pythonhosted.org/packages/6f/1c/20cdb593783f8f411839ce749ec9ae9e4298c2b2079b40295c3e6e2089e1/ruff-0.12.1-py3-none-win32.whl", hash = "sha256:d973fa626d4c8267848755bd0414211a456e99e125dcab147f24daa9e991a245", size = 10519495 }, { url = "https://files.pythonhosted.org/packages/68/ab/2542b14890d0f4872dd81b7b2a6aed3ac1786fae1ce9b17e11e6df9e31e3/ruff-0.12.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e07fbb89f2e9249f219d88331c833860489b49cdf4b032b8e4432e9b13e8a4b9", size = 13227653 },
{ url = "https://files.pythonhosted.org/packages/cf/56/7158bd8d3cf16394928f47c637d39a7d532268cd45220bdb6cd622985760/ruff-0.12.1-py3-none-win_amd64.whl", hash = "sha256:9e1123b1c033f77bd2590e4c1fe7e8ea72ef990a85d2484351d408224d603013", size = 11547485 }, { url = "https://files.pythonhosted.org/packages/22/16/2fbfc61047dbfd009c58a28369a693a1484ad15441723be1cd7fe69bb679/ruff-0.12.11-py3-none-win32.whl", hash = "sha256:c792e8f597c9c756e9bcd4d87cf407a00b60af77078c96f7b6366ea2ce9ba9d3", size = 11944270 },
{ url = "https://files.pythonhosted.org/packages/91/d0/6902c0d017259439d6fd2fd9393cea1cfe30169940118b007d5e0ea7e954/ruff-0.12.1-py3-none-win_arm64.whl", hash = "sha256:78ad09a022c64c13cc6077707f036bab0fac8cd7088772dcd1e5be21c5002efc", size = 10691209 }, { url = "https://files.pythonhosted.org/packages/08/a5/34276984705bfe069cd383101c45077ee029c3fe3b28225bf67aa35f0647/ruff-0.12.11-py3-none-win_amd64.whl", hash = "sha256:a3283325960307915b6deb3576b96919ee89432ebd9c48771ca12ee8afe4a0fd", size = 13046600 },
{ url = "https://files.pythonhosted.org/packages/84/a8/001d4a7c2b37623a3fd7463208267fb906df40ff31db496157549cfd6e72/ruff-0.12.11-py3-none-win_arm64.whl", hash = "sha256:bae4d6e6a2676f8fb0f98b74594a048bae1b944aab17e9f5d504062303c6dbea", size = 12135290 },
] ]
[[package]] [[package]]

View File

@ -7,11 +7,11 @@ env:
on: on:
pull_request: pull_request:
branches: ['master', 'main'] branches: ['main']
paths-ignore: ['docs/**'] paths-ignore: ['docs/**']
push: push:
branches: ['master', 'main'] branches: ['main']
paths-ignore: ['docs/**'] paths-ignore: ['docs/**']
concurrency: concurrency:
@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Code Repository - name: Checkout Code Repository
uses: actions/checkout@v4 uses: actions/checkout@v5
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
@ -65,7 +65,7 @@ jobs:
steps: steps:
- name: Checkout Code Repository - name: Checkout Code Repository
uses: actions/checkout@v4 uses: actions/checkout@v5
{%- if cookiecutter.use_docker == 'y' %} {%- if cookiecutter.use_docker == 'y' %}
- name: Set up Docker Buildx - name: Set up Docker Buildx

View File

@ -7,7 +7,7 @@ default_language_version:
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0 rev: v6.0.0
hooks: hooks:
- id: trailing-whitespace - id: trailing-whitespace
- id: end-of-file-fixer - id: end-of-file-fixer
@ -33,14 +33,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.25.0' rev: '1.27.0'
hooks: hooks:
- id: django-upgrade - id: django-upgrade
args: ['--target-version', '5.0'] 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.12.1 rev: v0.12.11
hooks: hooks:
# Linter # Linter
- id: ruff-check - id: ruff-check

View File

@ -1,4 +1,4 @@
FROM docker.io/node:22.14-bookworm-slim FROM docker.io/node:24.7-bookworm-slim
WORKDIR /app WORKDIR /app

View File

@ -1,4 +1,4 @@
FROM docker.io/amazon/aws-cli:2.27.12 FROM docker.io/amazon/aws-cli:2.28.0
# Clear entrypoint from the base image, otherwise it's always calling the aws CLI # Clear entrypoint from the base image, otherwise it's always calling the aws CLI
ENTRYPOINT [] ENTRYPOINT []

View File

@ -1,5 +1,5 @@
{% if cookiecutter.frontend_pipeline in ['Gulp', 'Webpack'] -%} {% if cookiecutter.frontend_pipeline in ['Gulp', 'Webpack'] -%}
FROM docker.io/node:22.14-bookworm-slim AS client-builder FROM docker.io/node:24.7-bookworm-slim AS client-builder
ARG APP_HOME=/app ARG APP_HOME=/app
WORKDIR ${APP_HOME} WORKDIR ${APP_HOME}

View File

@ -1,4 +1,4 @@
FROM docker.io/traefik:3.4.3 FROM docker.io/traefik:3.5.0
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

@ -15,7 +15,7 @@ from inside the `{{cookiecutter.project_slug}}/docs` directory.
{% else %} {% else %}
To build and serve docs, use the commands:: To build and serve docs, use the commands::
docker compose -f docker-compose.local.yml up docs docker compose -f docker-compose.docs.yml up
{% endif %} {% endif %}

View File

@ -101,7 +101,7 @@ function vendorScripts() {
// Image compression // Image compression
async function imgCompression() { async function imgCompression() {
const imagemin = (await import("gulp-imagemin")).default; const imagemin = (await import("gulp-imagemin")).default;
return src(`${paths.images}/*`) return src(`${paths.images}/*`, { encoding: false })
.pipe(imagemin()) // Compresses PNG, JPEG, GIF and SVG images .pipe(imagemin()) // Compresses PNG, JPEG, GIF and SVG images
.pipe(dest(paths.images)); .pipe(dest(paths.images));
} }

View File

@ -35,7 +35,7 @@
"webpack-merge": "^6.0.1" "webpack-merge": "^6.0.1"
}, },
"engines": { "engines": {
"node": "22.14" "node": "24.7"
}, },
"browserslist": [ "browserslist": [
"last 2 versions" "last 2 versions"

View File

@ -11,7 +11,7 @@ argon2-cffi==25.1.0 # https://github.com/hynek/argon2_cffi
{%- if cookiecutter.use_whitenoise == 'y' %} {%- if cookiecutter.use_whitenoise == 'y' %}
whitenoise==6.9.0 # https://github.com/evansd/whitenoise whitenoise==6.9.0 # https://github.com/evansd/whitenoise
{%- endif %} {%- endif %}
redis==6.2.0 # https://github.com/redis/redis-py redis==6.4.0 # https://github.com/redis/redis-py
{%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %} {%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %}
hiredis==3.2.1 # https://github.com/redis/hiredis-py hiredis==3.2.1 # https://github.com/redis/hiredis-py
{%- endif %} {%- endif %}
@ -32,7 +32,7 @@ uvicorn-worker==0.3.0 # https://github.com/Kludex/uvicorn-worker
django==5.1.11 # pyup: < 5.2 # https://www.djangoproject.com/ django==5.1.11 # pyup: < 5.2 # https://www.djangoproject.com/
django-environ==0.12.0 # https://github.com/joke2k/django-environ django-environ==0.12.0 # https://github.com/joke2k/django-environ
django-model-utils==5.0.0 # https://github.com/jazzband/django-model-utils django-model-utils==5.0.0 # https://github.com/jazzband/django-model-utils
django-allauth[mfa]==65.9.0 # https://github.com/pennersr/django-allauth django-allauth[mfa]==65.11.1 # https://github.com/pennersr/django-allauth
django-crispy-forms==2.4 # https://github.com/django-crispy-forms/django-crispy-forms django-crispy-forms==2.4 # https://github.com/django-crispy-forms/django-crispy-forms
crispy-bootstrap5==2025.6 # https://github.com/django-crispy-forms/crispy-bootstrap5 crispy-bootstrap5==2025.6 # https://github.com/django-crispy-forms/crispy-bootstrap5
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %} {%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
@ -41,7 +41,7 @@ django-compressor==4.5.1 # https://github.com/django-compressor/django-compress
django-redis==6.0.0 # https://github.com/jazzband/django-redis django-redis==6.0.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.16.0 # https://github.com/encode/django-rest-framework djangorestframework==3.16.1 # https://github.com/encode/django-rest-framework
django-cors-headers==4.7.0 # https://github.com/adamchainz/django-cors-headers django-cors-headers==4.7.0 # https://github.com/adamchainz/django-cors-headers
# DRF-spectacular for api documentation # DRF-spectacular for api documentation
drf-spectacular==0.28.0 # https://github.com/tfranzel/drf-spectacular drf-spectacular==0.28.0 # https://github.com/tfranzel/drf-spectacular

View File

@ -13,10 +13,10 @@ watchfiles==1.1.0 # https://github.com/samuelcolvin/watchfiles
# Testing # Testing
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
mypy==1.15.0 # https://github.com/python/mypy mypy==1.17.1 # https://github.com/python/mypy
django-stubs[compatible-mypy]==5.2.1 # https://github.com/typeddjango/django-stubs django-stubs[compatible-mypy]==5.2.2 # https://github.com/typeddjango/django-stubs
pytest==8.4.1 # https://github.com/pytest-dev/pytest pytest==8.4.1 # https://github.com/pytest-dev/pytest
pytest-sugar==1.0.0 # https://github.com/Teemu/pytest-sugar pytest-sugar==1.1.1 # https://github.com/Teemu/pytest-sugar
{%- if cookiecutter.use_drf == "y" %} {%- if cookiecutter.use_drf == "y" %}
djangorestframework-stubs==3.16.0 # https://github.com/typeddjango/djangorestframework-stubs djangorestframework-stubs==3.16.0 # https://github.com/typeddjango/djangorestframework-stubs
{%- endif %} {%- endif %}
@ -24,21 +24,21 @@ djangorestframework-stubs==3.16.0 # https://github.com/typeddjango/djangorestfr
# Documentation # Documentation
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
sphinx==8.2.3 # pyup: != 8.3.0 # https://github.com/sphinx-doc/sphinx sphinx==8.2.3 # pyup: != 8.3.0 # https://github.com/sphinx-doc/sphinx
sphinx-autobuild==2024.10.3 # https://github.com/GaretJax/sphinx-autobuild sphinx-autobuild==2025.8.25 # https://github.com/GaretJax/sphinx-autobuild
sphinx-rtd-theme==2.0.0 # https://pypi.org/project/sphinx-rtd-theme/ sphinx-rtd-theme==3.0.2 # https://pypi.org/project/sphinx-rtd-theme/
# Code quality # Code quality
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
ruff==0.12.1 # https://github.com/astral-sh/ruff ruff==0.12.11 # https://github.com/astral-sh/ruff
coverage==7.9.1 # https://github.com/nedbat/coveragepy coverage==7.10.6 # https://github.com/nedbat/coveragepy
djlint==1.36.4 # https://github.com/Riverside-Healthcare/djLint djlint==1.36.4 # https://github.com/Riverside-Healthcare/djLint
pre-commit==4.2.0 # https://github.com/pre-commit/pre-commit pre-commit==4.3.0 # https://github.com/pre-commit/pre-commit
# Django # Django
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
factory-boy==3.3.2 # https://github.com/FactoryBoy/factory_boy factory-boy==3.3.2 # https://github.com/FactoryBoy/factory_boy
django-debug-toolbar==5.2.0 # https://github.com/jazzband/django-debug-toolbar django-debug-toolbar==6.0.0 # https://github.com/jazzband/django-debug-toolbar
django-extensions==4.1 # https://github.com/django-extensions/django-extensions django-extensions==4.1 # https://github.com/django-extensions/django-extensions
django-coverage-plugin==3.1.1 # https://github.com/nedbat/django_coverage_plugin django-coverage-plugin==3.1.1 # https://github.com/nedbat/django_coverage_plugin
pytest-django==4.11.1 # https://github.com/pytest-dev/pytest-django pytest-django==4.11.1 # https://github.com/pytest-dev/pytest-django

View File

@ -5,10 +5,10 @@
gunicorn==23.0.0 # https://github.com/benoitc/gunicorn gunicorn==23.0.0 # https://github.com/benoitc/gunicorn
psycopg[c]==3.2.9 # https://github.com/psycopg/psycopg psycopg[c]==3.2.9 # https://github.com/psycopg/psycopg
{%- if cookiecutter.use_whitenoise == 'n'and cookiecutter.cloud_provider in ('AWS', 'GCP') %} {%- if cookiecutter.use_whitenoise == 'n'and cookiecutter.cloud_provider in ('AWS', 'GCP') %}
Collectfasta==3.3.0 # https://github.com/jasongi/collectfasta Collectfasta==3.3.1 # https://github.com/jasongi/collectfasta
{%- endif %} {%- endif %}
{%- if cookiecutter.use_sentry == "y" %} {%- if cookiecutter.use_sentry == "y" %}
sentry-sdk==2.32.0 # https://github.com/getsentry/sentry-python sentry-sdk==2.35.1 # 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==3.2.1 # https://github.com/redis/hiredis-py hiredis==3.2.1 # https://github.com/redis/hiredis-py
@ -24,21 +24,21 @@ django-storages[google]==1.14.6 # https://github.com/jschneier/django-storages
django-storages[azure]==1.14.6 # https://github.com/jschneier/django-storages django-storages[azure]==1.14.6 # https://github.com/jschneier/django-storages
{%- endif %} {%- endif %}
{%- if cookiecutter.mail_service == 'Mailgun' %} {%- if cookiecutter.mail_service == 'Mailgun' %}
django-anymail[mailgun]==13.0 # https://github.com/anymail/django-anymail django-anymail[mailgun]==13.0.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Amazon SES' %} {%- elif cookiecutter.mail_service == 'Amazon SES' %}
django-anymail[amazon-ses]==13.0 # https://github.com/anymail/django-anymail django-anymail[amazon-ses]==13.0.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Mailjet' %} {%- elif cookiecutter.mail_service == 'Mailjet' %}
django-anymail[mailjet]==13.0 # https://github.com/anymail/django-anymail django-anymail[mailjet]==13.0.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Mandrill' %} {%- elif cookiecutter.mail_service == 'Mandrill' %}
django-anymail[mandrill]==13.0 # https://github.com/anymail/django-anymail django-anymail[mandrill]==13.0.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Postmark' %} {%- elif cookiecutter.mail_service == 'Postmark' %}
django-anymail[postmark]==13.0 # https://github.com/anymail/django-anymail django-anymail[postmark]==13.0.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Sendgrid' %} {%- elif cookiecutter.mail_service == 'Sendgrid' %}
django-anymail[sendgrid]==13.0 # https://github.com/anymail/django-anymail django-anymail[sendgrid]==13.0.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Brevo' %} {%- elif cookiecutter.mail_service == 'Brevo' %}
django-anymail[brevo]==13.0 # https://github.com/anymail/django-anymail django-anymail[brevo]==13.0.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'SparkPost' %} {%- elif cookiecutter.mail_service == 'SparkPost' %}
django-anymail[sparkpost]==13.0 # https://github.com/anymail/django-anymail django-anymail[sparkpost]==13.0.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Other SMTP' %} {%- elif cookiecutter.mail_service == 'Other SMTP' %}
django-anymail==13.0 # https://github.com/anymail/django-anymail django-anymail==13.0.1 # https://github.com/anymail/django-anymail
{%- endif %} {%- endif %}