mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-09-21 19:32:34 +03:00
Merge branch 'cookiecutter-master'
This commit is contained in:
commit
59e03a61bb
30
.github/contributors.json
vendored
30
.github/contributors.json
vendored
|
@ -1478,5 +1478,35 @@
|
|||
"name": "Christian Jauvin",
|
||||
"github_login": "cjauvin",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "Plurific",
|
||||
"github_login": "paulschwenn",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "GitBib",
|
||||
"github_login": "GitBib",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "Freddy",
|
||||
"github_login": "Hraesvelg",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "aiden",
|
||||
"github_login": "anyidea",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "Michael V. Battista",
|
||||
"github_login": "mvbattista",
|
||||
"twitter_username": "mvbattista"
|
||||
},
|
||||
{
|
||||
"name": "Nix Siow",
|
||||
"github_login": "nixsiow",
|
||||
"twitter_username": "nixsiow"
|
||||
}
|
||||
]
|
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
|
@ -9,7 +9,7 @@ updates:
|
|||
schedule:
|
||||
interval: "daily"
|
||||
labels:
|
||||
- "update"
|
||||
- "project infrastructure"
|
||||
|
||||
# Update npm packages
|
||||
- package-ecosystem: "npm"
|
||||
|
|
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
|
@ -23,7 +23,7 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
cache: pip
|
||||
|
@ -54,7 +54,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
cache: pip
|
||||
|
@ -98,7 +98,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
cache: pip
|
||||
|
@ -110,6 +110,6 @@ jobs:
|
|||
run: pip install -r requirements.txt
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "18"
|
||||
node-version: "20"
|
||||
- name: Bare Metal ${{ matrix.script.name }}
|
||||
run: sh tests/test_bare.sh ${{ matrix.script.args }}
|
||||
|
|
2
.github/workflows/django-issue-checker.yml
vendored
2
.github/workflows/django-issue-checker.yml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- name: Install dependencies
|
||||
|
|
5
.github/workflows/issue-manager.yml
vendored
5
.github/workflows/issue-manager.yml
vendored
|
@ -23,18 +23,21 @@ jobs:
|
|||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: tiangolo/issue-manager@0.4.0
|
||||
- uses: tiangolo/issue-manager@0.4.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
config: >
|
||||
{
|
||||
"answered": {
|
||||
"delay": 864000,
|
||||
"message": "Assuming the question was answered, this will be automatically closed now."
|
||||
},
|
||||
"solved": {
|
||||
"delay": 864000,
|
||||
"message": "Assuming the original issue was solved, it will be automatically closed now."
|
||||
},
|
||||
"waiting": {
|
||||
"delay": 864000,
|
||||
"message": "Automatically closing after waiting for additional info. To re-open, please provide the additional information requested."
|
||||
}
|
||||
}
|
||||
|
|
2
.github/workflows/pre-commit-autoupdate.yml
vendored
2
.github/workflows/pre-commit-autoupdate.yml
vendored
|
@ -22,7 +22,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
|
|
2
.github/workflows/update-changelog.yml
vendored
2
.github/workflows/update-changelog.yml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- name: Install dependencies
|
||||
|
|
2
.github/workflows/update-contributors.yml
vendored
2
.github/workflows/update-contributors.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- name: Install dependencies
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
exclude: "{{cookiecutter.project_slug}}|.github/contributors.json|CHANGELOG.md|CONTRIBUTORS.md"
|
||||
default_stages: [commit]
|
||||
|
||||
default_language_version:
|
||||
python: python3.11
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.5.0
|
||||
|
@ -17,7 +20,7 @@ repos:
|
|||
- id: detect-private-key
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: "v3.1.0"
|
||||
rev: "v4.0.0-alpha.8"
|
||||
hooks:
|
||||
- id: prettier
|
||||
args: ["--tab-width", "2"]
|
||||
|
@ -30,17 +33,17 @@ repos:
|
|||
exclude: hooks/
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.11.0
|
||||
rev: 23.12.1
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.12.0
|
||||
rev: 5.13.2
|
||||
hooks:
|
||||
- id: isort
|
||||
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 6.1.0
|
||||
rev: 7.0.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
|
||||
|
|
257
CHANGELOG.md
257
CHANGELOG.md
|
@ -3,6 +3,263 @@ All enhancements and patches to Cookiecutter Django will be documented in this f
|
|||
|
||||
<!-- GENERATOR_PLACEHOLDER -->
|
||||
|
||||
## 2024.01.21
|
||||
|
||||
|
||||
### Documentation
|
||||
|
||||
- Update traefik doc links ([#4798](https://github.com/cookiecutter/cookiecutter-django/pull/4798))
|
||||
|
||||
### Updated
|
||||
|
||||
- Bump browser-sync from 2.29.3 to 3.0.2 in /{{cookiecutter.project_slug}} ([#4765](https://github.com/cookiecutter/cookiecutter-django/pull/4765))
|
||||
|
||||
## 2024.01.19
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update drf-spectacular to 0.27.1 ([#4797](https://github.com/cookiecutter/cookiecutter-django/pull/4797))
|
||||
|
||||
## 2024.01.17
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Add a test to cover `DJANGO_ADMIN_FORCE_ALLAUTH` ([#4790](https://github.com/cookiecutter/cookiecutter-django/pull/4790))
|
||||
|
||||
### Updated
|
||||
|
||||
- Bump webpack-bundle-tracker to 3.0.1 ([#4781](https://github.com/cookiecutter/cookiecutter-django/pull/4781))
|
||||
|
||||
- Update django-webpack-loader to 3.0.1 ([#4793](https://github.com/cookiecutter/cookiecutter-django/pull/4793))
|
||||
|
||||
- Bump postcss-loader to 8.0.0 ([#4795](https://github.com/cookiecutter/cookiecutter-django/pull/4795))
|
||||
|
||||
- Update uvicorn to 0.26.0 ([#4794](https://github.com/cookiecutter/cookiecutter-django/pull/4794))
|
||||
|
||||
## 2024.01.16
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Bump sass-loader from 13.3.3 to 14.0.0 in /{{cookiecutter.project_slug}} ([#4791](https://github.com/cookiecutter/cookiecutter-django/pull/4791))
|
||||
|
||||
## 2024.01.15
|
||||
|
||||
|
||||
### Documentation
|
||||
|
||||
- Update allauth documentation links ([#4786](https://github.com/cookiecutter/cookiecutter-django/pull/4786))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update django-allauth to 0.60.1 ([#4787](https://github.com/cookiecutter/cookiecutter-django/pull/4787))
|
||||
|
||||
## 2024.01.11
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update jinja2 to 3.1.3 ([#4784](https://github.com/cookiecutter/cookiecutter-django/pull/4784))
|
||||
|
||||
## 2024.01.10
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update sentry-sdk to 1.39.2 ([#4782](https://github.com/cookiecutter/cookiecutter-django/pull/4782))
|
||||
|
||||
## 2024.01.09
|
||||
|
||||
|
||||
### Documentation
|
||||
|
||||
- Update allauth settings documentation links ([#4769](https://github.com/cookiecutter/cookiecutter-django/pull/4769))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update django-allauth to 0.60.0 ([#4776](https://github.com/cookiecutter/cookiecutter-django/pull/4776))
|
||||
|
||||
- Update psycopg to 3.1.17 ([#4777](https://github.com/cookiecutter/cookiecutter-django/pull/4777))
|
||||
|
||||
## 2024.01.05
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Auto-update pre-commit hooks ([#4774](https://github.com/cookiecutter/cookiecutter-django/pull/4774))
|
||||
|
||||
- Update flake8 to 7.0.0 ([#4775](https://github.com/cookiecutter/cookiecutter-django/pull/4775))
|
||||
|
||||
## 2024.01.02
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update psycopg to 3.1.16 ([#4753](https://github.com/cookiecutter/cookiecutter-django/pull/4753))
|
||||
|
||||
- Update djlint to 1.34.1 ([#4773](https://github.com/cookiecutter/cookiecutter-django/pull/4773))
|
||||
|
||||
- Update uvicorn to 0.25.0 ([#4760](https://github.com/cookiecutter/cookiecutter-django/pull/4760))
|
||||
|
||||
- Auto-update pre-commit hooks ([#4749](https://github.com/cookiecutter/cookiecutter-django/pull/4749))
|
||||
|
||||
- Update black to 23.12.1 ([#4772](https://github.com/cookiecutter/cookiecutter-django/pull/4772))
|
||||
|
||||
- Update pillow to 10.2.0 ([#4770](https://github.com/cookiecutter/cookiecutter-django/pull/4770))
|
||||
|
||||
- Update django to 4.2.9 ([#4771](https://github.com/cookiecutter/cookiecutter-django/pull/4771))
|
||||
|
||||
- Update pytest to 7.4.4 ([#4767](https://github.com/cookiecutter/cookiecutter-django/pull/4767))
|
||||
|
||||
- Update coverage to 7.4.0 ([#4764](https://github.com/cookiecutter/cookiecutter-django/pull/4764))
|
||||
|
||||
## 2023.12.19
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Upgrade debian to 12 bookworm ([#4745](https://github.com/cookiecutter/cookiecutter-django/pull/4745))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update hiredis to 2.3.2 ([#4750](https://github.com/cookiecutter/cookiecutter-django/pull/4750))
|
||||
|
||||
## 2023.12.15
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update coverage to 7.3.3 ([#4748](https://github.com/cookiecutter/cookiecutter-django/pull/4748))
|
||||
|
||||
- Update psycopg to 3.1.15 ([#4747](https://github.com/cookiecutter/cookiecutter-django/pull/4747))
|
||||
|
||||
- Update sentry-sdk to 1.39.1 ([#4746](https://github.com/cookiecutter/cookiecutter-django/pull/4746))
|
||||
|
||||
- Auto-update pre-commit hooks ([#4743](https://github.com/cookiecutter/cookiecutter-django/pull/4743))
|
||||
|
||||
## 2023.12.13
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Auto-update pre-commit hooks ([#4740](https://github.com/cookiecutter/cookiecutter-django/pull/4740))
|
||||
|
||||
## 2023.12.12
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update django-allauth to 0.59.0 ([#4739](https://github.com/cookiecutter/cookiecutter-django/pull/4739))
|
||||
|
||||
- Update sentry-sdk to 1.39.0 ([#4738](https://github.com/cookiecutter/cookiecutter-django/pull/4738))
|
||||
|
||||
- Update black to 23.12.0 ([#4737](https://github.com/cookiecutter/cookiecutter-django/pull/4737))
|
||||
|
||||
- Auto-update pre-commit hooks ([#4736](https://github.com/cookiecutter/cookiecutter-django/pull/4736))
|
||||
|
||||
- Update drf-spectacular to 0.27.0 ([#4735](https://github.com/cookiecutter/cookiecutter-django/pull/4735))
|
||||
|
||||
## 2023.12.11
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Auto-update pre-commit hooks ([#4730](https://github.com/cookiecutter/cookiecutter-django/pull/4730))
|
||||
|
||||
## 2023.12.10
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update pre-commit to 3.6.0 ([#4728](https://github.com/cookiecutter/cookiecutter-django/pull/4728))
|
||||
|
||||
- Auto-update pre-commit hooks ([#4729](https://github.com/cookiecutter/cookiecutter-django/pull/4729))
|
||||
|
||||
## 2023.12.09
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Add missing __init__.py file to api module ([#4726](https://github.com/cookiecutter/cookiecutter-django/pull/4726))
|
||||
|
||||
## 2023.12.07
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Bump actions/setup-python from 4 to 5 ([#4723](https://github.com/cookiecutter/cookiecutter-django/pull/4723))
|
||||
|
||||
- Auto-update pre-commit hooks ([#4709](https://github.com/cookiecutter/cookiecutter-django/pull/4709))
|
||||
|
||||
- Bump traefik from 2.10.6 to 2.10.7 ([#4722](https://github.com/cookiecutter/cookiecutter-django/pull/4722))
|
||||
|
||||
## 2023.12.06
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Bump python from 3.11.6 to 3.11.7 ([#4719](https://github.com/cookiecutter/cookiecutter-django/pull/4719))
|
||||
|
||||
- Update mypy to 1.7.1, django-stubs to 4.2.7 and djangorestframework-stubs to 3.14.5 ([#4694](https://github.com/cookiecutter/cookiecutter-django/pull/4694))
|
||||
|
||||
## 2023.12.04
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update django to 4.2.8 ([#4713](https://github.com/cookiecutter/cookiecutter-django/pull/4713))
|
||||
|
||||
- Bump node from 18 to 20 ([#4283](https://github.com/cookiecutter/cookiecutter-django/pull/4283))
|
||||
|
||||
- Update psycopg to 3.1.14 ([#4711](https://github.com/cookiecutter/cookiecutter-django/pull/4711))
|
||||
|
||||
## 2023.12.02
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update mailpit to latest ([#4710](https://github.com/cookiecutter/cookiecutter-django/pull/4710))
|
||||
|
||||
## 2023.11.30
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Removed tmp mount in devcontainer.json. Fix #4686 ([#4708](https://github.com/cookiecutter/cookiecutter-django/pull/4708))
|
||||
|
||||
### Updated
|
||||
|
||||
- Bump traefik from 2.10.5 to 2.10.6 ([#4706](https://github.com/cookiecutter/cookiecutter-django/pull/4706))
|
||||
|
||||
## 2023.11.29
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update sentry-sdk to 1.38.0 ([#4705](https://github.com/cookiecutter/cookiecutter-django/pull/4705))
|
||||
|
||||
## 2023.11.28
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Excludes devcontainer.json from the pre-commit ([#4702](https://github.com/cookiecutter/cookiecutter-django/pull/4702))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update sphinx-rtd-theme to 2.0.0 ([#4700](https://github.com/cookiecutter/cookiecutter-django/pull/4700))
|
||||
|
||||
## 2023.11.24
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update sentry-sdk to 1.37.1 ([#4696](https://github.com/cookiecutter/cookiecutter-django/pull/4696))
|
||||
|
||||
- Update sentry-sdk to 1.37.0 ([#4695](https://github.com/cookiecutter/cookiecutter-django/pull/4695))
|
||||
|
||||
## 2023.11.22
|
||||
|
||||
|
||||
|
|
|
@ -194,6 +194,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td>scaramagus</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>aiden</td>
|
||||
<td>
|
||||
<a href="https://github.com/anyidea">anyidea</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Alberto Sanchez</td>
|
||||
<td>
|
||||
|
@ -831,6 +838,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Freddy</td>
|
||||
<td>
|
||||
<a href="https://github.com/Hraesvelg">Hraesvelg</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Fuzzwah</td>
|
||||
<td>
|
||||
|
@ -873,6 +887,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GitBib</td>
|
||||
<td>
|
||||
<a href="https://github.com/GitBib">GitBib</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Glenn Wiskur</td>
|
||||
<td>
|
||||
|
@ -1475,6 +1496,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Michael V. Battista</td>
|
||||
<td>
|
||||
<a href="https://github.com/mvbattista">mvbattista</a>
|
||||
</td>
|
||||
<td>mvbattista</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mike97M</td>
|
||||
<td>
|
||||
|
@ -1552,6 +1580,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nix Siow</td>
|
||||
<td>
|
||||
<a href="https://github.com/nixsiow">nixsiow</a>
|
||||
</td>
|
||||
<td>nixsiow</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Noah H</td>
|
||||
<td>
|
||||
|
@ -1650,6 +1685,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Plurific</td>
|
||||
<td>
|
||||
<a href="https://github.com/paulschwenn">paulschwenn</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Raony Guimarães Corrêa</td>
|
||||
<td>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
sphinx==7.2.6
|
||||
sphinx-rtd-theme==1.3.0
|
||||
sphinx-rtd-theme==2.0.0
|
||||
myst-parser==2.0.0
|
||||
|
|
|
@ -4,17 +4,17 @@ binaryornot==0.4.4
|
|||
|
||||
# Code quality
|
||||
# ------------------------------------------------------------------------------
|
||||
black==23.11.0
|
||||
isort==5.12.0
|
||||
flake8==6.1.0
|
||||
black==23.12.1
|
||||
isort==5.13.2
|
||||
flake8==7.0.0
|
||||
django-upgrade==1.15.0
|
||||
djlint==1.34.0
|
||||
pre-commit==3.5.0
|
||||
djlint==1.34.1
|
||||
pre-commit==3.6.0
|
||||
|
||||
# Testing
|
||||
# ------------------------------------------------------------------------------
|
||||
tox==4.11.3
|
||||
pytest==7.4.3
|
||||
tox==4.12.1
|
||||
pytest==7.4.4
|
||||
pytest-xdist==3.5.0
|
||||
pytest-cookies==0.7.0
|
||||
pytest-instafail==0.5.0
|
||||
|
@ -23,6 +23,6 @@ pyyaml==6.0.1
|
|||
# Scripting
|
||||
# ------------------------------------------------------------------------------
|
||||
PyGithub==2.1.1
|
||||
gitpython==3.1.40
|
||||
jinja2==3.1.2
|
||||
gitpython==3.1.41
|
||||
jinja2==3.1.3
|
||||
requests==2.31.0
|
||||
|
|
|
@ -212,7 +212,7 @@ class GitHubManager:
|
|||
for classifier in package_info["info"]["classifiers"]:
|
||||
# Usually in the form of "Framework :: Django :: 3.2"
|
||||
tokens = classifier.split(" ")
|
||||
if len(tokens) >= 5 and tokens[2].lower() == "django":
|
||||
if len(tokens) >= 5 and tokens[2].lower() == "django" and "." in tokens[4]:
|
||||
version = DjVersion.parse(tokens[4])
|
||||
if len(version) == 2:
|
||||
supported_dj_versions.append(version)
|
||||
|
|
2
setup.py
2
setup.py
|
@ -5,7 +5,7 @@ except ImportError:
|
|||
from distutils.core import setup
|
||||
|
||||
# We use calendar versioning
|
||||
version = "2023.11.22"
|
||||
version = "2024.01.21"
|
||||
|
||||
with open("README.md") as readme_file:
|
||||
long_description = readme_file.read()
|
||||
|
|
|
@ -11,11 +11,6 @@
|
|||
"target": "/home/dev-user/.bash_history",
|
||||
"type": "bind"
|
||||
},
|
||||
{
|
||||
"source": "/tmp",
|
||||
"target": "/tmp",
|
||||
"type": "bind"
|
||||
},
|
||||
{
|
||||
"source": "~/.ssh",
|
||||
"target": "/home/dev-user/.ssh",
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
exclude: '^docs/|/migrations/'
|
||||
exclude: '^docs/|/migrations/|devcontainer.json'
|
||||
default_stages: [commit]
|
||||
|
||||
default_language_version:
|
||||
python: python3.11
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.5.0
|
||||
|
@ -22,7 +25,7 @@ repos:
|
|||
- id: detect-private-key
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: v3.1.0
|
||||
rev: v4.0.0-alpha.8
|
||||
hooks:
|
||||
- id: prettier
|
||||
args: ['--tab-width', '2', '--single-quote']
|
||||
|
@ -41,22 +44,22 @@ repos:
|
|||
args: [--py311-plus]
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.11.0
|
||||
rev: 23.12.1
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.12.0
|
||||
rev: 5.13.2
|
||||
hooks:
|
||||
- id: isort
|
||||
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 6.1.0
|
||||
rev: 7.0.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
|
||||
- repo: https://github.com/Riverside-Healthcare/djLint
|
||||
rev: v1.34.0
|
||||
rev: v1.34.1
|
||||
hooks:
|
||||
- id: djlint-reformat-django
|
||||
files: "templates"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# define an alias for the specific python version used in this file.
|
||||
FROM python:3.11.6-slim-bullseye as python
|
||||
FROM python:3.11.7-slim-bookworm as python
|
||||
|
||||
# Python build stage
|
||||
FROM python as python-build-stage
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# define an alias for the specific python version used in this file.
|
||||
FROM python:3.11.6-slim-bullseye as python
|
||||
FROM python:3.11.7-slim-bookworm as python
|
||||
|
||||
|
||||
# Python build stage
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM node:18-bullseye-slim
|
||||
FROM node:20-bookworm-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% if cookiecutter.frontend_pipeline in ['Gulp', 'Webpack'] -%}
|
||||
FROM node:18-bullseye-slim as client-builder
|
||||
FROM node:20-bookworm-slim as client-builder
|
||||
|
||||
ARG APP_HOME=/app
|
||||
WORKDIR ${APP_HOME}
|
||||
|
@ -25,7 +25,7 @@ RUN npm run build
|
|||
|
||||
{%- endif %}
|
||||
# define an alias for the specific python version used in this file.
|
||||
FROM python:3.11.6-slim-bullseye as python
|
||||
FROM python:3.11.7-slim-bookworm as python
|
||||
|
||||
# Python build stage
|
||||
FROM python as python-build-stage
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM traefik:2.10.5
|
||||
FROM traefik:2.10.7
|
||||
RUN mkdir -p /etc/traefik/acme \
|
||||
&& touch /etc/traefik/acme/acme.json \
|
||||
&& chmod 600 /etc/traefik/acme/acme.json
|
||||
|
|
|
@ -6,7 +6,7 @@ entryPoints:
|
|||
# http
|
||||
address: ':80'
|
||||
http:
|
||||
# https://docs.traefik.io/routing/entrypoints/#entrypoint
|
||||
# https://doc.traefik.io/traefik/routing/entrypoints/#entrypoint
|
||||
redirections:
|
||||
entryPoint:
|
||||
to: web-secure
|
||||
|
@ -22,11 +22,11 @@ entryPoints:
|
|||
|
||||
certificatesResolvers:
|
||||
letsencrypt:
|
||||
# https://docs.traefik.io/master/https/acme/#lets-encrypt
|
||||
# https://doc.traefik.io/traefik/https/acme/#lets-encrypt
|
||||
acme:
|
||||
email: '{{ cookiecutter.email }}'
|
||||
storage: /etc/traefik/acme/acme.json
|
||||
# https://docs.traefik.io/master/https/acme/#httpchallenge
|
||||
# https://doc.traefik.io/traefik/https/acme/#httpchallenge
|
||||
httpChallenge:
|
||||
entryPoint: web
|
||||
|
||||
|
@ -44,7 +44,7 @@ http:
|
|||
- csrf
|
||||
service: django
|
||||
tls:
|
||||
# https://docs.traefik.io/master/routing/routers/#certresolver
|
||||
# https://doc.traefik.io/traefik/routing/routers/#certresolver
|
||||
certResolver: letsencrypt
|
||||
{%- if cookiecutter.use_celery == 'y' %}
|
||||
|
||||
|
@ -54,7 +54,7 @@ http:
|
|||
- flower
|
||||
service: flower
|
||||
tls:
|
||||
# https://docs.traefik.io/master/routing/routers/#certresolver
|
||||
# https://doc.traefik.io/traefik/master/routing/routers/#certresolver
|
||||
certResolver: letsencrypt
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.cloud_provider == 'None' %}
|
||||
|
@ -76,7 +76,7 @@ http:
|
|||
|
||||
middlewares:
|
||||
csrf:
|
||||
# https://docs.traefik.io/master/middlewares/headers/#hostsproxyheaders
|
||||
# https://doc.traefik.io/traefik/master/middlewares/http/headers/#hostsproxyheaders
|
||||
# https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
|
||||
headers:
|
||||
hostsProxyHeaders: ['X-CSRFToken']
|
||||
|
@ -102,7 +102,7 @@ http:
|
|||
{%- endif %}
|
||||
|
||||
providers:
|
||||
# https://docs.traefik.io/master/providers/file/
|
||||
# https://doc.traefik.io/traefik/master/providers/file/
|
||||
file:
|
||||
filename: /etc/traefik/traefik.yml
|
||||
watch: true
|
||||
|
|
|
@ -321,29 +321,29 @@ CELERY_TASK_SEND_SENT_EVENT = True
|
|||
# django-allauth
|
||||
# ------------------------------------------------------------------------------
|
||||
ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True)
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
# https://docs.allauth.org/en/latest/account/configuration.html
|
||||
ACCOUNT_AUTHENTICATION_METHOD = "email"
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
# https://docs.allauth.org/en/latest/account/configuration.html
|
||||
ACCOUNT_EMAIL_REQUIRED = True
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
# https://docs.allauth.org/en/latest/account/configuration.html
|
||||
ACCOUNT_USERNAME_REQUIRED = False
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
# https://docs.allauth.org/en/latest/account/configuration.html
|
||||
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
# https://docs.allauth.org/en/latest/account/configuration.html
|
||||
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
# https://docs.allauth.org/en/latest/account/configuration.html
|
||||
ACCOUNT_MAX_EMAIL_ADDRESSES = 1
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
# https://docs.allauth.org/en/latest/account/configuration.html
|
||||
ACCOUNT_LOGOUT_ON_GET = True
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
# https://docs.allauth.org/en/latest/account/configuration.html
|
||||
SOCIALACCOUNT_LOGIN_ON_GET = True
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html?highlight=SOCIALACCOUNT_LOGIN_ON_GET
|
||||
# https://docs.allauth.org/en/latest/account/configuration.html?highlight=SOCIALACCOUNT_LOGIN_ON_GET
|
||||
ACCOUNT_ADAPTER = "{{cookiecutter.project_slug}}.users.adapters.AccountAdapter"
|
||||
# https://django-allauth.readthedocs.io/en/latest/forms.html
|
||||
# https://docs.allauth.org/en/latest/account/forms.html
|
||||
ACCOUNT_FORMS = {"signup": "{{cookiecutter.project_slug}}.users.forms.UserSignupForm"}
|
||||
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||
# https://docs.allauth.org/en/latest/socialaccount/configuration.html
|
||||
SOCIALACCOUNT_ADAPTER = "{{cookiecutter.project_slug}}.users.adapters.SocialAccountAdapter"
|
||||
# https://django-allauth.readthedocs.io/en/latest/forms.html
|
||||
# https://docs.allauth.org/en/latest/socialaccount/configuration.html
|
||||
SOCIALACCOUNT_FORMS = {"signup": "{{cookiecutter.project_slug}}.users.forms.UserSocialSignupForm"}
|
||||
{% if cookiecutter.frontend_pipeline == 'Django Compressor' -%}
|
||||
# django-compressor
|
||||
|
|
|
@ -58,7 +58,7 @@ services:
|
|||
{%- if cookiecutter.use_mailpit == 'y' %}
|
||||
|
||||
mailpit:
|
||||
image: axllent/mailpit:v1.8
|
||||
image: axllent/mailpit:latest
|
||||
container_name: {{ cookiecutter.project_slug }}_local_mailpit
|
||||
ports:
|
||||
- "8025:8025"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"autoprefixer": "^10.4.0",
|
||||
"babel-loader": "^9.1.2",
|
||||
"bootstrap": "^5.2.3",
|
||||
"browser-sync": "^2.27.7",
|
||||
"browser-sync": "^3.0.2",
|
||||
"css-loader": "^6.5.1",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"concurrently": "^8.0.1",
|
||||
|
@ -24,18 +24,18 @@
|
|||
"node-sass-tilde-importer": "^1.0.2",
|
||||
"pixrem": "^5.0.0",
|
||||
"postcss": "^8.3.11",
|
||||
"postcss-loader": "^7.0.2",
|
||||
"postcss-loader": "^8.0.0",
|
||||
"postcss-preset-env": "^9.0.0",
|
||||
"sass": "^1.43.4",
|
||||
"sass-loader": "^13.2.0",
|
||||
"sass-loader": "^14.0.0",
|
||||
"webpack": "^5.65.0",
|
||||
"webpack-bundle-tracker": "^2.0.0",
|
||||
"webpack-bundle-tracker": "^3.0.1",
|
||||
"webpack-cli": "^5.0.1",
|
||||
"webpack-dev-server": "^4.6.0",
|
||||
"webpack-merge": "^5.8.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "18"
|
||||
"node": "20"
|
||||
},
|
||||
"browserslist": [
|
||||
"last 2 versions"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
python-slugify==8.0.1 # https://github.com/un33k/python-slugify
|
||||
Pillow==10.1.0 # https://github.com/python-pillow/Pillow
|
||||
Pillow==10.2.0 # https://github.com/python-pillow/Pillow
|
||||
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
|
||||
{%- if cookiecutter.windows == 'y' and cookiecutter.use_docker == 'n' %}
|
||||
rcssmin==1.1.0 --install-option="--without-c-extensions" # https://github.com/ndparker/rcssmin
|
||||
|
@ -13,7 +13,7 @@ whitenoise==6.6.0 # https://github.com/evansd/whitenoise
|
|||
{%- endif %}
|
||||
redis==5.0.1 # https://github.com/redis/redis-py
|
||||
{%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %}
|
||||
hiredis==2.2.3 # https://github.com/redis/hiredis-py
|
||||
hiredis==2.3.2 # https://github.com/redis/hiredis-py
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_celery == "y" %}
|
||||
celery==5.3.6 # pyup: < 6.0 # https://github.com/celery/celery
|
||||
|
@ -23,15 +23,15 @@ flower==2.0.1 # https://github.com/mher/flower
|
|||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_async == 'y' %}
|
||||
uvicorn[standard]==0.24.0.post1 # https://github.com/encode/uvicorn
|
||||
uvicorn[standard]==0.26.0 # https://github.com/encode/uvicorn
|
||||
{%- endif %}
|
||||
|
||||
# Django
|
||||
# ------------------------------------------------------------------------------
|
||||
django==4.2.7 # pyup: < 5.0 # https://www.djangoproject.com/
|
||||
django==4.2.9 # pyup: < 5.0 # https://www.djangoproject.com/
|
||||
django-environ==0.11.2 # https://github.com/joke2k/django-environ
|
||||
django-model-utils==4.3.1 # https://github.com/jazzband/django-model-utils
|
||||
django-allauth==0.58.2 # https://github.com/pennersr/django-allauth
|
||||
django-allauth==0.60.1 # https://github.com/pennersr/django-allauth
|
||||
django-crispy-forms==2.1 # https://github.com/django-crispy-forms/django-crispy-forms
|
||||
crispy-bootstrap5==2023.10 # https://github.com/django-crispy-forms/crispy-bootstrap5
|
||||
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
|
||||
|
@ -43,13 +43,13 @@ django-redis==5.4.0 # https://github.com/jazzband/django-redis
|
|||
djangorestframework==3.14.0 # https://github.com/encode/django-rest-framework
|
||||
django-cors-headers==4.3.1 # https://github.com/adamchainz/django-cors-headers
|
||||
# DRF-spectacular for api documentation
|
||||
drf-spectacular==0.26.5 # https://github.com/tfranzel/drf-spectacular
|
||||
drf-spectacular==0.27.1 # https://github.com/tfranzel/drf-spectacular
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.frontend_pipeline == 'Webpack' %}
|
||||
django-webpack-loader==2.0.1 # https://github.com/django-webpack/django-webpack-loader
|
||||
django-webpack-loader==3.0.1 # https://github.com/django-webpack/django-webpack-loader
|
||||
{%- endif %}
|
||||
|
||||
# Project
|
||||
# ------------------------------------------------------------------------------
|
||||
fontawesomefree==6.4.2 # https://github.com/FortAwesome/Font-Awesome
|
||||
django-import-export==3.3.3 # https://github.com/django-import-export/django-import-export
|
||||
fontawesomefree==6.5.1 # https://github.com/FortAwesome/Font-Awesome
|
||||
django-import-export==3.3.6 # https://github.com/django-import-export/django-import-export
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
Werkzeug[watchdog]==3.0.1 # https://github.com/pallets/werkzeug
|
||||
ipdb==0.13.13 # https://github.com/gotcha/ipdb
|
||||
{%- if cookiecutter.use_docker == 'y' %}
|
||||
psycopg[c]==3.1.13 # https://github.com/psycopg/psycopg
|
||||
psycopg[c]==3.1.17 # https://github.com/psycopg/psycopg
|
||||
{%- else %}
|
||||
psycopg[binary]==3.1.13 # https://github.com/psycopg/psycopg
|
||||
psycopg[binary]==3.1.17 # https://github.com/psycopg/psycopg
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_async == 'y' or cookiecutter.use_celery == 'y' %}
|
||||
watchfiles==0.21.0 # https://github.com/samuelcolvin/watchfiles
|
||||
|
@ -13,12 +13,12 @@ watchfiles==0.21.0 # https://github.com/samuelcolvin/watchfiles
|
|||
|
||||
# Testing
|
||||
# ------------------------------------------------------------------------------
|
||||
mypy==1.6.1 # https://github.com/python/mypy
|
||||
django-stubs[compatible-mypy]==4.2.6 # https://github.com/typeddjango/django-stubs
|
||||
pytest==7.4.3 # https://github.com/pytest-dev/pytest
|
||||
mypy==1.7.1 # https://github.com/python/mypy
|
||||
django-stubs[compatible-mypy]==4.2.7 # https://github.com/typeddjango/django-stubs
|
||||
pytest==7.4.4 # https://github.com/pytest-dev/pytest
|
||||
pytest-sugar==0.9.7 # https://github.com/Frozenball/pytest-sugar
|
||||
{%- if cookiecutter.use_drf == "y" %}
|
||||
djangorestframework-stubs[compatible-mypy]==3.14.4 # https://github.com/typeddjango/djangorestframework-stubs
|
||||
djangorestframework-stubs[compatible-mypy]==3.14.5 # https://github.com/typeddjango/djangorestframework-stubs
|
||||
{%- endif %}
|
||||
|
||||
# Documentation
|
||||
|
@ -29,16 +29,16 @@ sphinx-rtd-theme==1.3.0 # https://pypi.org/project/sphinx-rtd-theme/
|
|||
|
||||
# Code quality
|
||||
# ------------------------------------------------------------------------------
|
||||
flake8==6.1.0 # https://github.com/PyCQA/flake8
|
||||
flake8==7.0.0 # https://github.com/PyCQA/flake8
|
||||
flake8-isort==6.1.1 # https://github.com/gforcada/flake8-isort
|
||||
coverage==7.3.2 # https://github.com/nedbat/coveragepy
|
||||
black==23.11.0 # https://github.com/psf/black
|
||||
djlint==1.34.0 # https://github.com/Riverside-Healthcare/djLint
|
||||
coverage==7.4.0 # https://github.com/nedbat/coveragepy
|
||||
black==23.12.1 # https://github.com/psf/black
|
||||
djlint==1.34.1 # https://github.com/Riverside-Healthcare/djLint
|
||||
pylint-django==2.5.5 # https://github.com/PyCQA/pylint-django
|
||||
{%- if cookiecutter.use_celery == 'y' %}
|
||||
pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery
|
||||
{%- endif %}
|
||||
pre-commit==3.5.0 # https://github.com/pre-commit/pre-commit
|
||||
pre-commit==3.6.0 # https://github.com/pre-commit/pre-commit
|
||||
|
||||
# Django
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
-r base.txt
|
||||
|
||||
gunicorn==21.2.0 # https://github.com/benoitc/gunicorn
|
||||
psycopg[c]==3.1.13 # https://github.com/psycopg/psycopg
|
||||
psycopg[c]==3.1.17 # https://github.com/psycopg/psycopg
|
||||
{%- if cookiecutter.use_whitenoise == 'n' %}
|
||||
Collectfast==2.2.0 # https://github.com/antonagestam/collectfast
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_sentry == "y" %}
|
||||
sentry-sdk==1.37.0 # https://github.com/getsentry/sentry-python
|
||||
sentry-sdk==1.39.2 # https://github.com/getsentry/sentry-python
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_docker == "n" and cookiecutter.windows == "y" %}
|
||||
hiredis==2.2.3 # https://github.com/redis/hiredis-py
|
||||
hiredis==2.3.2 # https://github.com/redis/hiredis-py
|
||||
{%- endif %}
|
||||
|
||||
# Django
|
||||
|
|
|
@ -1 +1 @@
|
|||
python-3.11.6
|
||||
python-3.11.7
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
##basic build dependencies of various Django apps for Debian Bookworm 12.x
|
||||
#build-essential metapackage install: make, gcc, g++,
|
||||
build-essential
|
||||
#required to translate
|
||||
gettext
|
||||
python3-dev
|
||||
|
||||
##shared dependencies of:
|
||||
##Pillow, pylibmc
|
||||
zlib1g-dev
|
||||
|
||||
##Postgresql and psycopg2 dependencies
|
||||
libpq-dev
|
||||
|
||||
##Pillow dependencies
|
||||
libtiff5-dev
|
||||
libjpeg62-turbo-dev
|
||||
libfreetype6-dev
|
||||
liblcms2-dev
|
||||
libwebp-dev
|
||||
|
||||
##django-extensions
|
||||
libgraphviz-dev
|
|
@ -10,7 +10,7 @@ User = get_user_model()
|
|||
|
||||
if settings.DJANGO_ADMIN_FORCE_ALLAUTH:
|
||||
# Force the `admin` sign in process to go through the `django-allauth` workflow:
|
||||
# https://django-allauth.readthedocs.io/en/stable/advanced.html#admin
|
||||
# https://docs.allauth.org/en/latest/common/admin.html#admin
|
||||
admin.site.login = decorators.login_required(admin.site.login) # type: ignore[method-assign]
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
from importlib import reload
|
||||
|
||||
import pytest
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.urls import reverse
|
||||
from pytest_django.asserts import assertRedirects
|
||||
|
||||
from {{ cookiecutter.project_slug }}.users.models import User
|
||||
|
||||
|
@ -37,3 +43,25 @@ class TestUserAdmin:
|
|||
url = reverse("admin:users_user_change", kwargs={"object_id": user.pk})
|
||||
response = admin_client.get(url)
|
||||
assert response.status_code == 200
|
||||
|
||||
@pytest.fixture
|
||||
def force_allauth(self, settings):
|
||||
settings.DJANGO_ADMIN_FORCE_ALLAUTH = True
|
||||
# Reload the admin module to apply the setting change
|
||||
import {{ cookiecutter.project_slug }}.users.admin as users_admin # pylint: disable=import-outside-toplevel
|
||||
|
||||
try:
|
||||
reload(users_admin)
|
||||
except admin.sites.AlreadyRegistered:
|
||||
pass
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.usefixtures("force_allauth")
|
||||
def test_allauth_login(self, rf, settings):
|
||||
request = rf.get("/fake-url")
|
||||
request.user = AnonymousUser()
|
||||
response = admin.site.login(request)
|
||||
|
||||
# The `admin` login view should redirect to the `allauth` login view
|
||||
target_url = reverse(settings.LOGIN_URL) + "?next=" + request.path
|
||||
assertRedirects(response, target_url, fetch_redirect_response=False)
|
||||
|
|
Loading…
Reference in New Issue
Block a user