Merge branch 'master' into pyup-update-sphinx-6.2.1-to-7.0.1

This commit is contained in:
Bruno Alla 2023-07-04 23:58:16 +02:00 committed by GitHub
commit e6bf647820
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 1631 additions and 593 deletions

9
.github/FUNDING.yml vendored
View File

@ -2,11 +2,4 @@
github: [pydanny, browniebroke] github: [pydanny, browniebroke]
patreon: feldroy patreon: feldroy
open_collective: # Replace with a single Open Collective username open_collective: cookiecutter-django
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: ["https://www.patreon.com/browniebroke"]

View File

@ -53,6 +53,12 @@
"twitter_username": "sfdye", "twitter_username": "sfdye",
"is_core": true "is_core": true
}, },
{
"name": "Jelmer Draaijer",
"github_login": "foarsitter",
"twitter_username": "",
"is_core": true
},
{ {
"name": "18", "name": "18",
"github_login": "dezoito", "github_login": "dezoito",
@ -553,11 +559,6 @@
"github_login": "jvanbrug", "github_login": "jvanbrug",
"twitter_username": "" "twitter_username": ""
}, },
{
"name": "Jelmer Draaijer",
"github_login": "foarsitter",
"twitter_username": ""
},
{ {
"name": "Jerome Caisip", "name": "Jerome Caisip",
"github_login": "jeromecaisip", "github_login": "jeromecaisip",
@ -1392,5 +1393,20 @@
"name": "Birtibu", "name": "Birtibu",
"github_login": "Birtibu", "github_login": "Birtibu",
"twitter_username": "" "twitter_username": ""
},
{
"name": "Matheus Jardim Bernardes",
"github_login": "matheusjardimb",
"twitter_username": ""
},
{
"name": "masavini",
"github_login": "masavini",
"twitter_username": ""
},
{
"name": "Joseph Hanna",
"github_login": "sanchimenea",
"twitter_username": ""
} }
] ]

View File

@ -23,7 +23,7 @@ repos:
args: ["--tab-width", "2"] args: ["--tab-width", "2"]
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v3.4.0 rev: v3.8.0
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: [--py311-plus] args: [--py311-plus]

View File

@ -3,6 +3,258 @@ All enhancements and patches to Cookiecutter Django will be documented in this f
<!-- GENERATOR_PLACEHOLDER --> <!-- GENERATOR_PLACEHOLDER -->
## 2023.07.03
### Changed
- Add a devcontainer configuration with Docker ([#4198](https://github.com/cookiecutter/cookiecutter-django/pull/4198))
### Updated
- Update django-stubs to 4.2.3 ([#4430](https://github.com/cookiecutter/cookiecutter-django/pull/4430))
- Update django to 4.2.3 ([#4435](https://github.com/cookiecutter/cookiecutter-django/pull/4435))
## 2023.06.30
### Changed
- Add option to use django-allauth workflow in the admin ([#1921](https://github.com/cookiecutter/cookiecutter-django/pull/1921))
## 2023.06.29
### Changed
- Replace psycopg2 by psycopg3 ([#4421](https://github.com/cookiecutter/cookiecutter-django/pull/4421))
## 2023.06.28
### Changed
- Upgrade to django 4.2 ([#4393](https://github.com/cookiecutter/cookiecutter-django/pull/4393))
### Fixed
- Fix PostgreSQL version in GitHub workflow ([#4423](https://github.com/cookiecutter/cookiecutter-django/pull/4423))
### Updated
- Update werkzeug to 2.3.6 ([#4427](https://github.com/cookiecutter/cookiecutter-django/pull/4427))
- Update django-compressor to 4.4 ([#4422](https://github.com/cookiecutter/cookiecutter-django/pull/4422))
## 2023.06.27
### Changed
- Populate User `name` field during social auth ([#3968](https://github.com/cookiecutter/cookiecutter-django/pull/3968))
- Add djLint for HTML formatting and linting ([#4389](https://github.com/cookiecutter/cookiecutter-django/pull/4389))
### Fixed
- Only include prettier pre-commit hook with node-based front-end pipeline ([#4418](https://github.com/cookiecutter/cookiecutter-django/pull/4418))
### Updated
- Update djangorestframework-stubs to 3.14.2 ([#4420](https://github.com/cookiecutter/cookiecutter-django/pull/4420))
- Update django-stubs to 4.2.2 ([#4419](https://github.com/cookiecutter/cookiecutter-django/pull/4419))
## 2023.06.26
### Updated
- Update pytest to 7.4.0 ([#4412](https://github.com/cookiecutter/cookiecutter-django/pull/4412))
- Update redis to 4.6.0 ([#4415](https://github.com/cookiecutter/cookiecutter-django/pull/4415))
- Update mypy to 1.4.1 ([#4416](https://github.com/cookiecutter/cookiecutter-django/pull/4416))
## 2023.06.22
### Updated
- Update pygithub to 1.59.0 ([#4410](https://github.com/cookiecutter/cookiecutter-django/pull/4410))
- Update drf-spectacular to 0.26.3 ([#4411](https://github.com/cookiecutter/cookiecutter-django/pull/4411))
- Update sentry-sdk to 1.26.0 ([#4409](https://github.com/cookiecutter/cookiecutter-django/pull/4409))
## 2023.06.21
### Updated
- Upgrade traefik to 2.10.3 ([#4408](https://github.com/cookiecutter/cookiecutter-django/pull/4408))
## 2023.06.19
### Updated
- Auto-update pre-commit hooks ([#4405](https://github.com/cookiecutter/cookiecutter-django/pull/4405))
- Update celery to 5.3.1 ([#4404](https://github.com/cookiecutter/cookiecutter-django/pull/4404))
## 2023.06.18
### Changed
- Fix missing celery env variable when running compilemessages ([#4403](https://github.com/cookiecutter/cookiecutter-django/pull/4403))
### Updated
- Update flower to 2.0.0 ([#4402](https://github.com/cookiecutter/cookiecutter-django/pull/4402))
## 2023.06.17
## 2023.06.16
### Updated
- Update whitenoise to 6.5.0 ([#4400](https://github.com/cookiecutter/cookiecutter-django/pull/4400))
- Update django-redis to 5.3.0 ([#4399](https://github.com/cookiecutter/cookiecutter-django/pull/4399))
- Auto-update pre-commit hooks ([#4395](https://github.com/cookiecutter/cookiecutter-django/pull/4395))
## 2023.06.14
### Updated
- Update django-cors-headers to 4.1.0 ([#4391](https://github.com/cookiecutter/cookiecutter-django/pull/4391))
- Update django-upgrade to 1.14.0 ([#4394](https://github.com/cookiecutter/cookiecutter-django/pull/4394))
- Update django-webpack-loader to 2.0.1 ([#4392](https://github.com/cookiecutter/cookiecutter-django/pull/4392))
- Update pre-commit to 3.3.3 ([#4390](https://github.com/cookiecutter/cookiecutter-django/pull/4390))
## 2023.06.11
### Updated
- Update pytest to 7.3.2 ([#4384](https://github.com/cookiecutter/cookiecutter-django/pull/4384))
- Auto-update pre-commit hooks ([#4385](https://github.com/cookiecutter/cookiecutter-django/pull/4385))
## 2023.06.09
### Fixed
- Fix missing `compilemessages` step before deploying to prod ([#4363](https://github.com/cookiecutter/cookiecutter-django/pull/4363))
## 2023.06.08
### Fixed
- Fix failure in user view test caused by translations ([#4374](https://github.com/cookiecutter/cookiecutter-django/pull/4374))
### Updated
- Update to Python 3.11.4 in production Docker compose ([#4378](https://github.com/cookiecutter/cookiecutter-django/pull/4378))
- Update to Python 3.11.4 in docs Docker compose ([#4379](https://github.com/cookiecutter/cookiecutter-django/pull/4379))
- Update to Python 3.11.4 in local Docker compose ([#4380](https://github.com/cookiecutter/cookiecutter-django/pull/4380))
- Update celery to 5.3.0 ([#4369](https://github.com/cookiecutter/cookiecutter-django/pull/4369))
- Update werkzeug to 2.3.5 ([#4377](https://github.com/cookiecutter/cookiecutter-django/pull/4377))
## 2023.06.07
### Changed
- Replace `runserver` with `runserver_plus` ([#4373](https://github.com/cookiecutter/cookiecutter-django/pull/4373))
- Add translations for Brazilian Portuguese ([#4367](https://github.com/cookiecutter/cookiecutter-django/pull/4367))
### Updated
- Update sentry-sdk to 1.25.1 ([#4376](https://github.com/cookiecutter/cookiecutter-django/pull/4376))
- Update django-extensions to 3.2.3 ([#4372](https://github.com/cookiecutter/cookiecutter-django/pull/4372))
- Update djangorestframework-stubs to 3.14.1 ([#4366](https://github.com/cookiecutter/cookiecutter-django/pull/4366))
- Update django-stubs to 4.2.1 ([#4365](https://github.com/cookiecutter/cookiecutter-django/pull/4365))
- Update mypy to 1.3.0 ([#4327](https://github.com/cookiecutter/cookiecutter-django/pull/4327))
## 2023.06.02
### Updated
- Update sentry-sdk to 1.25.0 ([#4364](https://github.com/cookiecutter/cookiecutter-django/pull/4364))
## 2023.05.30
### Updated
- Update hiredis to 2.2.3 ([#4360](https://github.com/cookiecutter/cookiecutter-django/pull/4360))
- Update django-debug-toolbar to 4.1.0 ([#4359](https://github.com/cookiecutter/cookiecutter-django/pull/4359))
- Update redis to 4.5.5 ([#4358](https://github.com/cookiecutter/cookiecutter-django/pull/4358))
- Update django-anymail to 10.0 ([#4357](https://github.com/cookiecutter/cookiecutter-django/pull/4357))
- Update coverage to 7.2.7 ([#4356](https://github.com/cookiecutter/cookiecutter-django/pull/4356))
## 2023.05.28
## 2023.05.24
### Fixed
- Prevent Celery restarts on media file changes ([#4352](https://github.com/cookiecutter/cookiecutter-django/pull/4352))
### Updated
- Update coverage to 7.2.6 ([#4351](https://github.com/cookiecutter/cookiecutter-django/pull/4351))
## 2023.05.23
### Changed
- Fix compatibility webpack-bundle-tracker&gt;=2.0.0 js library required after upgrade django-webpack-loader&gt;=2.0.0 ([#4350](https://github.com/cookiecutter/cookiecutter-django/pull/4350))
### Updated
- Update sphinx-rtd-theme to 1.2.1 ([#4348](https://github.com/cookiecutter/cookiecutter-django/pull/4348))
- Update sentry-sdk to 1.24.0 ([#4349](https://github.com/cookiecutter/cookiecutter-django/pull/4349))
- Bump webpack-bundle-tracker from 1.8.1 to 2.0.0 in /{{cookiecutter.project_slug}} ([#4347](https://github.com/cookiecutter/cookiecutter-django/pull/4347))
- Update django-webpack-loader to 2.0.0 ([#4345](https://github.com/cookiecutter/cookiecutter-django/pull/4345))
- Update pytest-xdist to 3.3.1 ([#4344](https://github.com/cookiecutter/cookiecutter-django/pull/4344))
- Update requests to 2.31.0 ([#4346](https://github.com/cookiecutter/cookiecutter-django/pull/4346))
## 2023.05.18 ## 2023.05.18

View File

@ -74,6 +74,13 @@ accept and merge pull requests.
</td> </td>
<td>sfdye</td> <td>sfdye</td>
</tr> </tr>
<tr>
<td>Jelmer Draaijer</td>
<td>
<a href="https://github.com/foarsitter">foarsitter</a>
</td>
<td></td>
</tr>
</table> </table>
_Audrey is also the creator of Cookiecutter. Audrey and Daniel are on _Audrey is also the creator of Cookiecutter. Audrey and Daniel are on
@ -1006,13 +1013,6 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>Jelmer Draaijer</td>
<td>
<a href="https://github.com/foarsitter">foarsitter</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>Jens Nilsson</td> <td>Jens Nilsson</td>
<td> <td>
@ -1069,6 +1069,13 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>Joseph Hanna</td>
<td>
<a href="https://github.com/sanchimenea">sanchimenea</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>jugglinmike</td> <td>jugglinmike</td>
<td> <td>
@ -1307,6 +1314,13 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>masavini</td>
<td>
<a href="https://github.com/masavini">masavini</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>Mateusz Ostaszewski</td> <td>Mateusz Ostaszewski</td>
<td> <td>
@ -1314,6 +1328,13 @@ Listed in alphabetical order.
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td>Matheus Jardim Bernardes</td>
<td>
<a href="https://github.com/matheusjardimb">matheusjardimb</a>
</td>
<td></td>
</tr>
<tr> <tr>
<td>Mathijs Hoogland</td> <td>Mathijs Hoogland</td>
<td> <td>

View File

@ -19,7 +19,7 @@ production-ready Django projects quickly.
## Features ## Features
- For Django 4.1 - For Django 4.2
- Works with Python 3.11 - Works with Python 3.11
- Renders Django projects with 100% starting test coverage - Renders Django projects with 100% starting test coverage
- Twitter [Bootstrap](https://github.com/twbs/bootstrap) v5 - Twitter [Bootstrap](https://github.com/twbs/bootstrap) v5
@ -51,15 +51,16 @@ _These features can be enabled during initial project setup._
## Constraints ## Constraints
- Only maintained 3rd party libraries are used. - Only maintained 3rd party libraries are used.
- Uses PostgreSQL everywhere: 10.19 - 14.1 ([MySQL fork](https://github.com/mabdullahadeel/cookiecutter-django-mysql) also available). - Uses PostgreSQL everywhere: 10 - 15 ([MySQL fork](https://github.com/mabdullahadeel/cookiecutter-django-mysql) also available).
- Environment variables for configuration (This won't work with Apache/mod_wsgi). - Environment variables for configuration (This won't work with Apache/mod_wsgi).
## Support this Project! ## Support this Project!
This project is run by volunteers. Please support them in their efforts to maintain and improve Cookiecutter Django: This project is an open source project run by volunteers. You can sponsor us via [OpenCollective](https://opencollective.com/cookiecutter-django) or individually via GitHub Sponsors:
- Daniel Roy Greenfeld, Project Lead ([GitHub](https://github.com/pydanny), [Patreon](https://www.patreon.com/danielroygreenfeld)): expertise in Django and AWS ELB. - Daniel Roy Greenfeld, Project Lead ([GitHub](https://github.com/pydanny), [Patreon](https://www.patreon.com/danielroygreenfeld)): expertise in Django and AWS ELB.
- Fabio C. Barrionuevo, Core Developer ([GitHub](https://github.com/luzfcb)): expertise in Python/Django, hands-on DevOps and frontend experience. - Fabio C. Barrionuevo, Core Developer ([GitHub](https://github.com/luzfcb)): expertise in Python/Django, hands-on DevOps and frontend experience.
- Bruno Alla, Core Developer ([GitHub](https://github.com/browniebroke)): expertise in Python/Django and DevOps.
- Nikita Shupeyko, Core Developer ([GitHub](https://github.com/webyneter)): expertise in Python/Django, hands-on DevOps and frontend experience. - Nikita Shupeyko, Core Developer ([GitHub](https://github.com/webyneter)): expertise in Python/Django, hands-on DevOps and frontend experience.
Projects that provide financial support to the maintainers: Projects that provide financial support to the maintainers:
@ -125,14 +126,19 @@ Answer the prompts with your own desired [options](http://cookiecutter-django.re
Choose from 1, 2 [1]: 1 Choose from 1, 2 [1]: 1
timezone [UTC]: America/Los_Angeles timezone [UTC]: America/Los_Angeles
windows [n]: n windows [n]: n
use_pycharm [n]: y Select an editor to use. The choices are:
1 - None
2 - PyCharm
3 - VS Code
Choose from 1, 2, 3 [1]: 1
use_docker [n]: n use_docker [n]: n
Select postgresql_version: Select postgresql_version:
1 - 14 1 - 15
2 - 13 2 - 14
3 - 12 3 - 13
4 - 11 4 - 12
5 - 10 5 - 11
6 - 10
Choose from 1, 2, 3, 4, 5 [1]: 1 Choose from 1, 2, 3, 4, 5 [1]: 1
Select cloud_provider: Select cloud_provider:
1 - AWS 1 - AWS

View File

@ -16,9 +16,9 @@
"username_type": ["username", "email"], "username_type": ["username", "email"],
"timezone": "UTC", "timezone": "UTC",
"windows": "n", "windows": "n",
"use_pycharm": "n", "editor": ["None", "PyCharm", "VS Code"],
"use_docker": "n", "use_docker": "n",
"postgresql_version": ["14", "13", "12", "11", "10"], "postgresql_version": ["15", "14", "13", "12", "11", "10"],
"cloud_provider": ["AWS", "GCP", "Azure", "None"], "cloud_provider": ["AWS", "GCP", "Azure", "None"],
"mail_service": [ "mail_service": [
"Mailgun", "Mailgun",

View File

@ -53,20 +53,25 @@ timezone:
windows: windows:
Indicates whether the project should be configured for development on Windows. Indicates whether the project should be configured for development on Windows.
use_pycharm: editor:
Indicates whether the project should be configured for development with PyCharm_. Select an editor to use. The choices are:
1. None
2. PyCharm_
3. `VS Code`_
use_docker: use_docker:
Indicates whether the project should be configured to use Docker_ and `Docker Compose`_. Indicates whether the project should be configured to use Docker_, `Docker Compose`_ and `devcontainer`_.
postgresql_version: postgresql_version:
Select a PostgreSQL_ version to use. The choices are: Select a PostgreSQL_ version to use. The choices are:
1. 14 1. 15
2. 13 2. 14
3. 12 3. 13
4. 11 4. 12
5. 10 5. 11
6. 10
cloud_provider: cloud_provider:
Select a cloud provider for static & media files. The choices are: Select a cloud provider for static & media files. The choices are:
@ -148,9 +153,11 @@ debug:
.. _Apache Software License 2.0: http://www.apache.org/licenses/LICENSE-2.0 .. _Apache Software License 2.0: http://www.apache.org/licenses/LICENSE-2.0
.. _PyCharm: https://www.jetbrains.com/pycharm/ .. _PyCharm: https://www.jetbrains.com/pycharm/
.. _VS Code: https://github.com/microsoft/vscode
.. _Docker: https://github.com/docker/docker .. _Docker: https://github.com/docker/docker
.. _Docker Compose: https://docs.docker.com/compose/ .. _Docker Compose: https://docs.docker.com/compose/
.. _devcontainer: https://containers.dev/
.. _PostgreSQL: https://www.postgresql.org/docs/ .. _PostgreSQL: https://www.postgresql.org/docs/

View File

@ -1,3 +1,3 @@
sphinx==7.0.1 sphinx==7.0.1
sphinx-rtd-theme==1.2.1 sphinx-rtd-theme==1.2.2
myst-parser==1.0.0 myst-parser==2.0.0

View File

@ -81,3 +81,6 @@ Other Environment Settings
DJANGO_ACCOUNT_ALLOW_REGISTRATION (=True) DJANGO_ACCOUNT_ALLOW_REGISTRATION (=True)
Allow enable or disable user registration through `django-allauth` without disabling other characteristics like authentication and account management. (Django Setting: ACCOUNT_ALLOW_REGISTRATION) Allow enable or disable user registration through `django-allauth` without disabling other characteristics like authentication and account management. (Django Setting: ACCOUNT_ALLOW_REGISTRATION)
DJANGO_ADMIN_FORCE_ALLAUTH (=False)
Force the `admin` sign in process to go through the `django-allauth` workflow.

View File

@ -74,12 +74,13 @@ def remove_pycharm_files():
def remove_docker_files(): def remove_docker_files():
shutil.rmtree(".devcontainer")
shutil.rmtree("compose") shutil.rmtree("compose")
file_names = ["local.yml", "production.yml", ".dockerignore"] file_names = ["local.yml", "production.yml", ".dockerignore"]
for file_name in file_names: for file_name in file_names:
os.remove(file_name) os.remove(file_name)
if "{{ cookiecutter.use_pycharm }}".lower() == "y": if "{{ cookiecutter.editor }}".lower() == "PyCharm":
file_names = ["docker_compose_up_django.xml", "docker_compose_up_docs.xml"] file_names = ["docker_compose_up_django.xml", "docker_compose_up_docs.xml"]
for file_name in file_names: for file_name in file_names:
os.remove(os.path.join(".idea", "runConfigurations", file_name)) os.remove(os.path.join(".idea", "runConfigurations", file_name))
@ -96,10 +97,6 @@ def remove_heroku_files():
# don't remove the file if we are using travisci but not using heroku # don't remove the file if we are using travisci but not using heroku
continue continue
os.remove(file_name) os.remove(file_name)
remove_heroku_build_hooks()
def remove_heroku_build_hooks():
shutil.rmtree("bin") shutil.rmtree("bin")
@ -194,7 +191,9 @@ def handle_js_runner(choice, use_docker, use_async):
"gulp-uglify-es", "gulp-uglify-es",
] ]
if not use_docker: if not use_docker:
dev_django_cmd = "uvicorn config.asgi:application --reload" if use_async else "python manage.py runserver" dev_django_cmd = (
"uvicorn config.asgi:application --reload" if use_async else "python manage.py runserver_plus"
)
scripts.update( scripts.update(
{ {
"dev": "concurrently npm:dev:*", "dev": "concurrently npm:dev:*",
@ -429,7 +428,7 @@ def main():
if "{{ cookiecutter.username_type }}" == "username": if "{{ cookiecutter.username_type }}" == "username":
remove_custom_user_manager_files() remove_custom_user_manager_files()
if "{{ cookiecutter.use_pycharm }}".lower() == "n": if "{{ cookiecutter.editor }}".lower() != "PyCharm":
remove_pycharm_files() remove_pycharm_files()
if "{{ cookiecutter.use_docker }}".lower() == "y": if "{{ cookiecutter.use_docker }}".lower() == "y":
@ -442,15 +441,13 @@ def main():
if "{{ cookiecutter.use_heroku }}".lower() == "n": if "{{ cookiecutter.use_heroku }}".lower() == "n":
remove_heroku_files() remove_heroku_files()
elif "{{ cookiecutter.frontend_pipeline }}" != "Django Compressor":
remove_heroku_build_hooks()
if "{{ cookiecutter.use_docker }}".lower() == "n" and "{{ cookiecutter.use_heroku }}".lower() == "n": if "{{ cookiecutter.use_docker }}".lower() == "n" and "{{ cookiecutter.use_heroku }}".lower() == "n":
if "{{ cookiecutter.keep_local_envs_in_vcs }}".lower() == "y": if "{{ cookiecutter.keep_local_envs_in_vcs }}".lower() == "y":
print( print(
INFO + ".env(s) are only utilized when Docker Compose and/or " INFO + ".env(s) are only utilized when Docker Compose and/or "
"Heroku support is enabled so keeping them does not " "Heroku support is enabled so keeping them does not make sense "
"make sense given your current setup." + TERMINATOR "given your current setup." + TERMINATOR
) )
remove_envs_and_associated_files() remove_envs_and_associated_files()
else: else:

View File

@ -27,3 +27,24 @@ known_first_party = [
"scripts", "scripts",
"hooks", "hooks",
] ]
# ==== djLint ====
[tool.djlint]
blank_line_after_tag = "load,extends"
close_void_tags = true
format_css = true
format_js = true
# TODO: remove T002 when fixed https://github.com/Riverside-Healthcare/djLint/issues/687
ignore = "H006,H030,H031,T002,T028"
ignore_blocks = "raw"
include = "H017,H035"
indent = 2
max_line_length = 119
profile = "jinja"
[tool.djlint.css]
indent_size = 2
[tool.djlint.js]
indent_size = 2

View File

@ -7,13 +7,14 @@ binaryornot==0.4.4
black==23.3.0 black==23.3.0
isort==5.12.0 isort==5.12.0
flake8==6.0.0 flake8==6.0.0
django-upgrade==1.13.0 django-upgrade==1.14.0
pre-commit==3.3.2 djlint==1.31.1
pre-commit==3.3.3
# Testing # Testing
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
tox==4.5.1 tox==4.6.3
pytest==7.3.1 pytest==7.4.0
pytest-xdist==3.3.1 pytest-xdist==3.3.1
pytest-cookies==0.7.0 pytest-cookies==0.7.0
pytest-instafail==0.5.0 pytest-instafail==0.5.0
@ -21,7 +22,7 @@ pyyaml==6.0
# Scripting # Scripting
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
PyGithub==1.58.2 PyGithub==1.59.0
gitpython==3.1.31 gitpython==3.1.31
jinja2==3.1.2 jinja2==3.1.2
requests==2.31.0 requests==2.31.0

View File

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

View File

@ -52,10 +52,12 @@ SUPPORTED_COMBINATIONS = [
{"open_source_license": "Not open source"}, {"open_source_license": "Not open source"},
{"windows": "y"}, {"windows": "y"},
{"windows": "n"}, {"windows": "n"},
{"use_pycharm": "y"}, {"editor": "None"},
{"use_pycharm": "n"}, {"editor": "PyCharm"},
{"editor": "VS Code"},
{"use_docker": "y"}, {"use_docker": "y"},
{"use_docker": "n"}, {"use_docker": "n"},
{"postgresql_version": "15"},
{"postgresql_version": "14"}, {"postgresql_version": "14"},
{"postgresql_version": "13"}, {"postgresql_version": "13"},
{"postgresql_version": "12"}, {"postgresql_version": "12"},
@ -231,7 +233,7 @@ def test_django_upgrade_passes(cookies, context_override):
try: try:
sh.django_upgrade( sh.django_upgrade(
"--target-version", "--target-version",
"4.1", "4.2",
*python_files, *python_files,
_cwd=str(result.project_path), _cwd=str(result.project_path),
) )
@ -239,6 +241,32 @@ def test_django_upgrade_passes(cookies, context_override):
pytest.fail(e.stdout.decode()) pytest.fail(e.stdout.decode())
@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id)
def test_djlint_lint_passes(cookies, context_override):
"""Check whether generated project passes djLint --lint."""
result = cookies.bake(extra_context=context_override)
autofixable_rules = "H014,T001"
# TODO: remove T002 when fixed https://github.com/Riverside-Healthcare/djLint/issues/687
ignored_rules = "H006,H030,H031,T002"
try:
sh.djlint("--lint", "--ignore", f"{autofixable_rules},{ignored_rules}", ".", _cwd=str(result.project_path))
except sh.ErrorReturnCode as e:
pytest.fail(e.stdout.decode())
@auto_fixable
@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id)
def test_djlint_check_passes(cookies, context_override):
"""Check whether generated project passes djLint --check."""
result = cookies.bake(extra_context=context_override)
try:
sh.djlint("--check", ".", _cwd=str(result.project_path))
except sh.ErrorReturnCode as e:
pytest.fail(e.stdout.decode())
@pytest.mark.parametrize( @pytest.mark.parametrize(
["use_docker", "expected_test_script"], ["use_docker", "expected_test_script"],
[ [
@ -347,14 +375,15 @@ def test_error_if_incompatible(cookies, context, invalid_context):
@pytest.mark.parametrize( @pytest.mark.parametrize(
["use_pycharm", "pycharm_docs_exist"], ["editor", "pycharm_docs_exist"],
[ [
("n", False), ("None", False),
("y", True), ("PyCharm", True),
("VS Code", False),
], ],
) )
def test_pycharm_docs_removed(cookies, context, use_pycharm, pycharm_docs_exist): def test_pycharm_docs_removed(cookies, context, editor, pycharm_docs_exist):
context.update({"use_pycharm": use_pycharm}) context.update({"editor": editor})
result = cookies.bake(extra_context=context) result = cookies.bake(extra_context=context)
with open(f"{result.project_path}/docs/index.rst") as f: with open(f"{result.project_path}/docs/index.rst") as f:

View File

@ -0,0 +1,20 @@
#
# .bashrc.override.sh
#
# persistent bash history
HISTFILE=~/.bash_history
PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
# set some django env vars
source /entrypoint
# restore default shell options
set +o errexit
set +o pipefail
set +o nounset
# start ssh-agent
# https://code.visualstudio.com/docs/remote/troubleshooting
eval "$(ssh-agent -s)"

View File

@ -0,0 +1,87 @@
// For format details, see https://containers.dev/implementors/json_reference/
{
"name": "{{cookiecutter.project_slug}}_dev",
"dockerComposeFile": [
"../local.yml"
],
"init": true,
"mounts": [
{
"source": "./.devcontainer/bash_history",
"target": "/home/dev-user/.bash_history",
"type": "bind"
},
{
"source": "~/.ssh",
"target": "/tmp",
"type": "bind"
},
{
"source": "~/.ssh",
"target": "/home/dev-user/.ssh",
"type": "bind"
}
],
// Tells devcontainer.json supporting services / tools whether they should run
// /bin/sh -c "while sleep 1000; do :; done" when starting the container instead of the containers default command
"overrideCommand": true,
"service": "django",
// "remoteEnv": {"PATH": "/home/dev-user/.local/bin:${containerEnv:PATH}"},
"remoteUser": "dev-user",
"workspaceFolder": "/app",
// Set *default* container specific settings.json values on container create.
"customizations": {
{%- if cookiecutter.editor == "VS Code" %}
"vscode": {
"settings": {
"editor.formatOnSave": true,
"[python]": {
"analysis.autoImportCompletions": true,
"analysis.typeCheckingMode": "basic",
"defaultInterpreterPath": "/usr/local/bin/python",
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
// Uncomment when fixed
// https://github.com/microsoft/vscode-remote-release/issues/8474
// "editor.defaultFormatter": "ms-python.black-formatter",
"formatting.blackPath": "/usr/local/bin/black",
"formatting.provider": "black",
"languageServer": "Pylance",
// "linting.banditPath": "/usr/local/py-utils/bin/bandit",
"linting.enabled": true,
"linting.flake8Enabled": true,
"linting.flake8Path": "/usr/local/bin/flake8",
"linting.mypyEnabled": true,
"linting.mypyPath": "/usr/local/bin/mypy",
"linting.pycodestylePath": "/usr/local/bin/pycodestyle",
// "linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"linting.pylintEnabled": true,
"linting.pylintPath": "/usr/local/bin/pylint"
}
},
// https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_vs-code-specific-properties
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"davidanson.vscode-markdownlint",
"mrmlnc.vscode-duplicate",
"visualstudioexptteam.vscodeintellicode",
"visualstudioexptteam.intellicode-api-usage-examples",
// python
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.isort",
"ms-python.black-formatter",
// django
"batisteo.vscode-django"
]
}
{%- endif %}
},
// Uncomment the next line if you want start specific services in your Docker Compose config.
// "runServices": [],
// Uncomment the next line if you want to keep your containers running after VS Code shuts down.
// "shutdownAction": "none",
// Uncomment the next line to run commands after the container is created.
"postCreateCommand": "cat .devcontainer/bashrc.override.sh >> ~/.bashrc"
}

View File

@ -49,7 +49,7 @@ jobs:
- 6379:6379 - 6379:6379
{%- endif %} {%- endif %}
postgres: postgres:
image: postgres:12 image: postgres:{{ cookiecutter.postgresql_version }}
ports: ports:
- 5432:5432 - 5432:5432
env: env:

View File

@ -161,11 +161,10 @@ typings/
!.vscode/extensions.json !.vscode/extensions.json
*.code-workspace *.code-workspace
# Local History for Visual Studio Code # Local History for devcontainer
.history/ .devcontainer/bash_history
{% if cookiecutter.editor == 'PyCharm' -%}
{% if cookiecutter.use_pycharm == 'y' -%}
# Provided default Pycharm Run/Debug Configurations should be tracked by git # Provided default Pycharm Run/Debug Configurations should be tracked by git
# In case of local modifications made by Pycharm, use update-index command # In case of local modifications made by Pycharm, use update-index command
# for each changed file, like this: # for each changed file, like this:

View File

@ -0,0 +1,33 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="runserver_plus" type="Python.DjangoServer" factoryName="Django server" singleton="true">
<module name="{{ cookiecutter.project_slug }}" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.local" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<PathMappingSettings>
<option name="pathMappings">
<list>
<mapping local-root="$PROJECT_DIR$" remote-root="/app" />
</list>
</option>
</PathMappingSettings>
<option name="launchJavascriptDebuger" value="false" />
<option name="port" value="8000" />
<option name="host" value="0.0.0.0" />
<option name="additionalOptions" value="" />
<option name="browserUrl" value="" />
<option name="runTestServer" value="false" />
<option name="runNoReload" value="false" />
<option name="useCustomRunCommand" value="true" />
<option name="customRunCommand" value="runserver_plus" />
<method />
</configuration>
</component>

View File

@ -16,6 +16,7 @@ repos:
- id: check-case-conflict - id: check-case-conflict
- id: check-docstring-first - id: check-docstring-first
- id: detect-private-key - id: detect-private-key
{%- if cookiecutter.frontend_pipeline in ["Webpack", "Gulp"] %}
- repo: https://github.com/pre-commit/mirrors-prettier - repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.0-alpha.9-for-vscode rev: v3.0.0-alpha.9-for-vscode
@ -23,15 +24,16 @@ repos:
- id: prettier - id: prettier
args: ['--tab-width', '2', '--single-quote'] args: ['--tab-width', '2', '--single-quote']
exclude: '{{cookiecutter.project_slug}}/templates/' exclude: '{{cookiecutter.project_slug}}/templates/'
{%- endif %}
- repo: https://github.com/adamchainz/django-upgrade - repo: https://github.com/adamchainz/django-upgrade
rev: '1.13.0' rev: '1.14.0'
hooks: hooks:
- id: django-upgrade - id: django-upgrade
args: ['--target-version', '4.1'] args: ['--target-version', '4.2']
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v3.4.0 rev: v3.7.0
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: [--py311-plus] args: [--py311-plus]
@ -51,6 +53,12 @@ repos:
hooks: hooks:
- id: flake8 - id: flake8
- repo: https://github.com/Riverside-Healthcare/djLint
rev: v1.31.1
hooks:
- id: djlint-reformat-django
- id: djlint-django
# sets up .pre-commit-ci.yaml to ensure pre-commit dependencies stay up to date # sets up .pre-commit-ci.yaml to ensure pre-commit dependencies stay up to date
ci: ci:
autoupdate_schedule: weekly autoupdate_schedule: weekly

View File

@ -1,4 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
{%- if cookiecutter.frontend_pipeline == "Django Compressor" %}
compress_enabled() { compress_enabled() {
python << END python << END
@ -19,4 +20,7 @@ if compress_enabled
then then
python manage.py compress python manage.py compress
fi fi
{%- endif %}
python manage.py collectstatic --noinput python manage.py collectstatic --noinput
python manage.py compilemessages -i site-packages

View File

@ -1,5 +1,5 @@
# define an alias for the specific python version used in this file. # define an alias for the specific python version used in this file.
FROM python:3.11.3-slim-bullseye as python FROM python:3.11.4-slim-bullseye as python
# Python build stage # Python build stage
FROM python as python-build-stage FROM python as python-build-stage
@ -33,6 +33,18 @@ ENV BUILD_ENV ${BUILD_ENVIRONMENT}
WORKDIR ${APP_HOME} WORKDIR ${APP_HOME}
{% if cookiecutter.use_docker == "y" %}
# devcontainer dependencies and utils
RUN apt-get update && apt-get install --no-install-recommends -y \
sudo git bash-completion nano ssh
# Create devcontainer user and add it to sudoers
RUN groupadd --gid 1000 dev-user \
&& useradd --uid 1000 --gid dev-user --shell /bin/bash --create-home dev-user \
&& echo dev-user ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/dev-user \
&& chmod 0440 /etc/sudoers.d/dev-user
{% endif %}
# Install required system dependencies # Install required system dependencies
RUN apt-get update && apt-get install --no-install-recommends -y \ RUN apt-get update && apt-get install --no-install-recommends -y \
# psycopg2 dependencies # psycopg2 dependencies
@ -49,7 +61,7 @@ COPY --from=python-build-stage /usr/src/app/wheels /wheels/
# use wheels to install python dependencies # use wheels to install python dependencies
RUN pip install --no-cache-dir --no-index --find-links=/wheels/ /wheels/* \ RUN pip install --no-cache-dir --no-index --find-links=/wheels/ /wheels/* \
&& rm -rf /wheels/ && rm -rf /wheels/
COPY ./compose/production/django/entrypoint /entrypoint COPY ./compose/production/django/entrypoint /entrypoint
RUN sed -i 's/\r$//g' /entrypoint RUN sed -i 's/\r$//g' /entrypoint

View File

@ -5,4 +5,4 @@ set -o nounset
rm -f './celerybeat.pid' rm -f './celerybeat.pid'
exec watchfiles celery.__main__.main --args '-A config.celery_app beat -l INFO' exec watchfiles --filter python celery.__main__.main --args '-A config.celery_app beat -l INFO'

View File

@ -3,6 +3,6 @@
set -o errexit set -o errexit
set -o nounset set -o nounset
exec watchfiles celery.__main__.main \ exec watchfiles --filter python celery.__main__.main \
--args \ --args \
"-A config.celery_app -b \"${CELERY_BROKER_URL}\" flower --basic_auth=\"${CELERY_FLOWER_USER}:${CELERY_FLOWER_PASSWORD}\"" "-A config.celery_app -b \"${CELERY_BROKER_URL}\" flower --basic_auth=\"${CELERY_FLOWER_USER}:${CELERY_FLOWER_PASSWORD}\""

View File

@ -4,4 +4,4 @@ set -o errexit
set -o nounset set -o nounset
exec watchfiles celery.__main__.main --args '-A config.celery_app worker -l INFO' exec watchfiles --filter python celery.__main__.main --args '-A config.celery_app worker -l INFO'

View File

@ -9,5 +9,5 @@ python manage.py migrate
{%- if cookiecutter.use_async == 'y' %} {%- if cookiecutter.use_async == 'y' %}
exec uvicorn config.asgi:application --host 0.0.0.0 --reload --reload-include '*.html' exec uvicorn config.asgi:application --host 0.0.0.0 --reload --reload-include '*.html'
{%- else %} {%- else %}
exec python manage.py runserver 0.0.0.0:8000 exec python manage.py runserver_plus 0.0.0.0:8000
{%- endif %} {%- endif %}

View File

@ -1,5 +1,5 @@
# define an alias for the specific python version used in this file. # define an alias for the specific python version used in this file.
FROM python:3.11.3-slim-bullseye as python FROM python:3.11.4-slim-bullseye as python
# Python build stage # Python build stage

View File

@ -25,7 +25,7 @@ RUN npm run build
{%- endif %} {%- endif %}
# define an alias for the specific python version used in this file. # define an alias for the specific python version used in this file.
FROM python:3.11.3-slim-bullseye as python FROM python:3.11.4-slim-bullseye as python
# Python build stage # Python build stage
FROM python as python-build-stage FROM python as python-build-stage
@ -121,4 +121,11 @@ RUN chown django:django ${APP_HOME}
USER django USER django
RUN DATABASE_URL="" \
{%- if cookiecutter.use_celery == "y" %}
CELERY_BROKER_URL="" \
{%- endif %}
DJANGO_SETTINGS_MODULE="config.settings.test" \
python manage.py compilemessages
ENTRYPOINT ["/entrypoint"] ENTRYPOINT ["/entrypoint"]

View File

@ -20,14 +20,14 @@ python << END
import sys import sys
import time import time
import psycopg2 import psycopg
suggest_unrecoverable_after = 30 suggest_unrecoverable_after = 30
start = time.time() start = time.time()
while True: while True:
try: try:
psycopg2.connect( psycopg.connect(
dbname="${POSTGRES_DB}", dbname="${POSTGRES_DB}",
user="${POSTGRES_USER}", user="${POSTGRES_USER}",
password="${POSTGRES_PASSWORD}", password="${POSTGRES_PASSWORD}",
@ -35,7 +35,7 @@ while True:
port="${POSTGRES_PORT}", port="${POSTGRES_PORT}",
) )
break break
except psycopg2.OperationalError as error: except psycopg.OperationalError as error:
sys.stderr.write("Waiting for PostgreSQL to become available...\n") sys.stderr.write("Waiting for PostgreSQL to become available...\n")
if time.time() - start > suggest_unrecoverable_after: if time.time() - start > suggest_unrecoverable_after:

View File

@ -1,4 +1,4 @@
FROM traefik:2.10.1 FROM traefik:2.10.3
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

@ -26,6 +26,12 @@ DEBUG = env.bool("DJANGO_DEBUG", False)
TIME_ZONE = "{{ cookiecutter.timezone }}" TIME_ZONE = "{{ cookiecutter.timezone }}"
# https://docs.djangoproject.com/en/dev/ref/settings/#language-code # https://docs.djangoproject.com/en/dev/ref/settings/#language-code
LANGUAGE_CODE = "en-us" LANGUAGE_CODE = "en-us"
# https://docs.djangoproject.com/en/dev/ref/settings/#languages
# from django.utils.translation import gettext_lazy as _
# LANGUAGES = [
# ('en', _('English')),
# ('pt-br', _('Português')),
# ]
# https://docs.djangoproject.com/en/dev/ref/settings/#site-id # https://docs.djangoproject.com/en/dev/ref/settings/#site-id
SITE_ID = 1 SITE_ID = 1
# https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n # https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
@ -244,6 +250,9 @@ ADMIN_URL = "admin/"
ADMINS = [("""{{cookiecutter.author_name}}""", "{{cookiecutter.email}}")] ADMINS = [("""{{cookiecutter.author_name}}""", "{{cookiecutter.email}}")]
# https://docs.djangoproject.com/en/dev/ref/settings/#managers # https://docs.djangoproject.com/en/dev/ref/settings/#managers
MANAGERS = ADMINS MANAGERS = ADMINS
# https://cookiecutter-django.readthedocs.io/en/latest/settings.html#other-environment-settings
# Force the `admin` sign in process to go through the `django-allauth` workflow
DJANGO_ADMIN_FORCE_ALLAUTH = env.bool('DJANGO_ADMIN_FORCE_ALLAUTH', default=False)
# LOGGING # LOGGING
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -10,7 +10,7 @@ Welcome to {{ cookiecutter.project_name }}'s documentation!
:maxdepth: 2 :maxdepth: 2
:caption: Contents: :caption: Contents:
howto{% if cookiecutter.use_pycharm == 'y' %} howto{% if cookiecutter.editor == 'PyCharm' %}
pycharm/configuration{% endif %} pycharm/configuration{% endif %}
users users

View File

@ -0,0 +1,32 @@
# Translations
Start by configuring the `LANGUAGES` settings in `base.py`, by uncommenting languages you are willing to support. Then, translations strings will be placed in this folder when running:
```bash
{% if cookiecutter.use_docker == 'y' %}docker-compose -f local.yml run --rm django {% endif %}python manage.py makemessages -all --no-location
```
This should generate `django.po` (stands for Portable Object) files under each locale `<locale name>/LC_MESSAGES/django.po`. Each translatable string in the codebase is collected with its `msgid` and need to be translated as `msgstr`, for example:
```po
msgid "users"
msgstr "utilisateurs"
```
Once all translations are done, they need to be compiled into `.mo` files (stands for Machine Object), which are the actual binary files used by the application:
```bash
{% if cookiecutter.use_docker == 'y' %}docker-compose -f local.yml run --rm django {% endif %}python manage.py compilemessages
```
Note that the `.po` files are NOT used by the application directly, so if the `.mo` files are out of dates, the content won't appear as translated even if the `.po` files are up-to-date.
## Production
The production image runs `compilemessages` automatically at build time, so as long as your translated source files (PO) are up-to-date, you're good to go.
## Add a new language
1. Update the [`LANGUAGES` setting](https://docs.djangoproject.com/en/stable/ref/settings/#std-setting-LANGUAGES) to your project's base settings.
2. Create the locale folder for the language next to this file, e.g. `fr_FR` for French. Make sure the case is correct.
3. Run `makemessages` (as instructed above) to generate the PO files for the new language.

View File

@ -1,6 +0,0 @@
Translations
============
Translations will be placed in this folder when running::
python manage.py makemessages

View File

@ -0,0 +1,12 @@
# Translations for the {{ cookiecutter.project_name }} project
# Copyright (C) {% now 'utc', '%Y' %} {{ cookiecutter.author_name }}
# {{ cookiecutter.author_name }} <{{ cookiecutter.email }}>, {% now 'utc', '%Y' %}.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: {{ cookiecutter.version }}\n"
"Language: en-US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View File

@ -0,0 +1,315 @@
# Translations for the {{ cookiecutter.project_name }} project
# Copyright (C) {% now 'utc', '%Y' %} {{ cookiecutter.author_name }}
# {{ cookiecutter.author_name }} <{{ cookiecutter.email }}>, {% now 'utc', '%Y' %}.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: {{ cookiecutter.version }}\n"
"Language: pt-BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: {{cookiecutter.project_slug}}/templates/account/account_inactive.html:5
#: {{cookiecutter.project_slug}}/templates/account/account_inactive.html:8
msgid "Account Inactive"
msgstr "Conta Inativa"
#: {{cookiecutter.project_slug}}/templates/account/account_inactive.html:10
msgid "This account is inactive."
msgstr "Esta conta está inativa."
#: {{cookiecutter.project_slug}}/templates/account/email.html:7
msgid "Account"
msgstr "Conta"
#: {{cookiecutter.project_slug}}/templates/account/email.html:10
msgid "E-mail Addresses"
msgstr "Endereços de E-mail"
#: {{cookiecutter.project_slug}}/templates/account/email.html:13
msgid "The following e-mail addresses are associated with your account:"
msgstr "Os seguintes endereços de e-mail estão associados à sua conta:"
#: {{cookiecutter.project_slug}}/templates/account/email.html:27
msgid "Verified"
msgstr "Verificado"
#: {{cookiecutter.project_slug}}/templates/account/email.html:29
msgid "Unverified"
msgstr "Não verificado"
#: {{cookiecutter.project_slug}}/templates/account/email.html:31
msgid "Primary"
msgstr "Primário"
#: {{cookiecutter.project_slug}}/templates/account/email.html:37
msgid "Make Primary"
msgstr "Tornar Primário"
#: {{cookiecutter.project_slug}}/templates/account/email.html:38
msgid "Re-send Verification"
msgstr "Reenviar verificação"
#: {{cookiecutter.project_slug}}/templates/account/email.html:39
msgid "Remove"
msgstr "Remover"
#: {{cookiecutter.project_slug}}/templates/account/email.html:46
msgid "Warning:"
msgstr "Aviso:"
#: {{cookiecutter.project_slug}}/templates/account/email.html:46
msgid ""
"You currently do not have any e-mail address set up. You should really add "
"an e-mail address so you can receive notifications, reset your password, etc."
msgstr ""
"No momento, você não tem nenhum endereço de e-mail configurado. Você "
"realmente deve adicionar um endereço de e-mail para receber notificações, "
"redefinir sua senha etc."
#: {{cookiecutter.project_slug}}/templates/account/email.html:51
msgid "Add E-mail Address"
msgstr "Adicionar Endereço de E-mail"
#: {{cookiecutter.project_slug}}/templates/account/email.html:56
msgid "Add E-mail"
msgstr "Adicionar E-mail"
#: {{cookiecutter.project_slug}}/templates/account/email.html:66
msgid "Do you really want to remove the selected e-mail address?"
msgstr "Você realmente deseja remover o endereço de e-mail selecionado?"
#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:6
#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:10
msgid "Confirm E-mail Address"
msgstr "Confirme o endereço de e-mail"
#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:16
#, python-format
msgid ""
"Please confirm that <a href=\"mailto:%(email)s\">%(email)s</a> is an e-mail "
"address for user %(user_display)s."
msgstr ""
"Confirme se <a href=\"mailto:%(email)s\">%(email)s</a> é um endereço de "
"e-mail do usuário %(user_display)s."
#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:20
msgid "Confirm"
msgstr "Confirmar"
#: {{cookiecutter.project_slug}}/templates/account/email_confirm.html:27
#, python-format
msgid ""
"This e-mail confirmation link expired or is invalid. Please <a href="
"\"%(email_url)s\">issue a new e-mail confirmation request</a>."
msgstr "Este link de confirmação de e-mail expirou ou é inválido. "
"Por favor, <a href=\"%(email_url)s\">emita um novo pedido de confirmação por e-mail</a>."
#: {{cookiecutter.project_slug}}/templates/account/login.html:7
#: {{cookiecutter.project_slug}}/templates/account/login.html:11
#: {{cookiecutter.project_slug}}/templates/account/login.html:56
#: {{cookiecutter.project_slug}}/templates/base.html:72
msgid "Sign In"
msgstr "Entrar"
#: {{cookiecutter.project_slug}}/templates/account/login.html:17
msgid "Please sign in with one of your existing third party accounts:"
msgstr "Faça login com uma de suas contas de terceiros existentes:"
#: {{cookiecutter.project_slug}}/templates/account/login.html:19
#, python-format
msgid ""
"Or, <a href=\"%(signup_url)s\">sign up</a> for a %(site_name)s account and "
"sign in below:"
msgstr "Ou, <a href=\"%(signup_url)s\">cadastre-se</a> para uma conta em %(site_name)s e entre abaixo:"
#: {{cookiecutter.project_slug}}/templates/account/login.html:32
msgid "or"
msgstr "or"
#: {{cookiecutter.project_slug}}/templates/account/login.html:41
#, python-format
msgid ""
"If you have not created an account yet, then please <a href=\"%(signup_url)s"
"\">sign up</a> first."
msgstr "Se você ainda não criou uma conta, <a href=\"%(signup_url)s"
"\">registre-se primeiro</a>."
#: {{cookiecutter.project_slug}}/templates/account/login.html:55
msgid "Forgot Password?"
msgstr "Esqueceu sua senha?"
#: {{cookiecutter.project_slug}}/templates/account/logout.html:5
#: {{cookiecutter.project_slug}}/templates/account/logout.html:8
#: {{cookiecutter.project_slug}}/templates/account/logout.html:17
#: {{cookiecutter.project_slug}}/templates/base.html:61
msgid "Sign Out"
msgstr "Sair"
#: {{cookiecutter.project_slug}}/templates/account/logout.html:10
msgid "Are you sure you want to sign out?"
msgstr "Você tem certeza que deseja sair?"
#: {{cookiecutter.project_slug}}/templates/account/password_change.html:6
#: {{cookiecutter.project_slug}}/templates/account/password_change.html:9
#: {{cookiecutter.project_slug}}/templates/account/password_change.html:14
#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:5
#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:8
#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html:4
#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html:7
msgid "Change Password"
msgstr "Alterar Senha"
#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:7
#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:11
#: {{cookiecutter.project_slug}}/templates/account/password_reset_done.html:6
#: {{cookiecutter.project_slug}}/templates/account/password_reset_done.html:9
msgid "Password Reset"
msgstr "Redefinição de senha"
#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:16
msgid ""
"Forgotten your password? Enter your e-mail address below, and we'll send you "
"an e-mail allowing you to reset it."
msgstr "Esqueceu sua senha? Digite seu endereço de e-mail abaixo e enviaremos um e-mail permitindo que você o redefina."
#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:21
msgid "Reset My Password"
msgstr "Redefinir minha senha"
#: {{cookiecutter.project_slug}}/templates/account/password_reset.html:24
msgid "Please contact us if you have any trouble resetting your password."
msgstr "Entre em contato conosco se tiver algum problema para redefinir sua senha."
#: {{cookiecutter.project_slug}}/templates/account/password_reset_done.html:15
msgid ""
"We have sent you an e-mail. Please contact us if you do not receive it "
"within a few minutes."
msgstr "Enviamos um e-mail para você. Entre em contato conosco se você não recebê-lo dentro de alguns minutos."
#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:8
msgid "Bad Token"
msgstr "Token Inválido"
#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:12
#, python-format
msgid ""
"The password reset link was invalid, possibly because it has already been "
"used. Please request a <a href=\"%(passwd_reset_url)s\">new password reset</"
"a>."
msgstr "O link de redefinição de senha era inválido, possivelmente porque já foi usado. "
"<a href=\"%(passwd_reset_url)s\">Solicite uma nova redefinição de senha</a>."
#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:18
msgid "change password"
msgstr "alterar senha"
#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html:21
#: {{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html:8
msgid "Your password is now changed."
msgstr "Sua senha agora foi alterada."
#: {{cookiecutter.project_slug}}/templates/account/password_set.html:6
#: {{cookiecutter.project_slug}}/templates/account/password_set.html:9
#: {{cookiecutter.project_slug}}/templates/account/password_set.html:14
msgid "Set Password"
msgstr "Definir Senha"
#: {{cookiecutter.project_slug}}/templates/account/signup.html:6
msgid "Signup"
msgstr "Cadastro"
#: {{cookiecutter.project_slug}}/templates/account/signup.html:9
#: {{cookiecutter.project_slug}}/templates/account/signup.html:19
#: {{cookiecutter.project_slug}}/templates/base.html:67
msgid "Sign Up"
msgstr "Cadastro"
#: {{cookiecutter.project_slug}}/templates/account/signup.html:11
#, python-format
msgid ""
"Already have an account? Then please <a href=\"%(login_url)s\">sign in</a>."
msgstr "já tem uma conta? Então, por favor, faça <a href=\"%(login_url)s\">login</a>."
#: {{cookiecutter.project_slug}}/templates/account/signup_closed.html:5
#: {{cookiecutter.project_slug}}/templates/account/signup_closed.html:8
msgid "Sign Up Closed"
msgstr "Inscrições encerradas"
#: {{cookiecutter.project_slug}}/templates/account/signup_closed.html:10
msgid "We are sorry, but the sign up is currently closed."
msgstr "Lamentamos, mas as inscrições estão encerradas no momento."
#: {{cookiecutter.project_slug}}/templates/account/verification_sent.html:5
#: {{cookiecutter.project_slug}}/templates/account/verification_sent.html:8
#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:5
#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:8
msgid "Verify Your E-mail Address"
msgstr "Verifique seu endereço de e-mail"
#: {{cookiecutter.project_slug}}/templates/account/verification_sent.html:10
msgid ""
"We have sent an e-mail to you for verification. Follow the link provided to "
"finalize the signup process. Please contact us if you do not receive it "
"within a few minutes."
msgstr "Enviamos um e-mail para você para verificação. Siga o link fornecido para finalizar o processo de inscrição. Entre em contato conosco se você não recebê-lo dentro de alguns minutos."
#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:12
msgid ""
"This part of the site requires us to verify that\n"
"you are who you claim to be. For this purpose, we require that you\n"
"verify ownership of your e-mail address. "
msgstr "Esta parte do site exige que verifiquemos se você é quem afirma ser.\n"
"Para esse fim, exigimos que você verifique a propriedade\n"
"do seu endereço de e-mail."
#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:16
msgid ""
"We have sent an e-mail to you for\n"
"verification. Please click on the link inside this e-mail. Please\n"
"contact us if you do not receive it within a few minutes."
msgstr "Enviamos um e-mail para você para verificação.\n"
"Por favor, clique no link dentro deste e-mail.\n"
"Entre em contato conosco se você não recebê-lo dentro de alguns minutos."
#: {{cookiecutter.project_slug}}/templates/account/verified_email_required.html:20
#, python-format
msgid ""
"<strong>Note:</strong> you can still <a href=\"%(email_url)s\">change your e-"
"mail address</a>."
msgstr "<strong>Nota</strong>: você ainda pode <a href=\"%(email_url)s\">alterar seu endereço de e-mail</a>."
#: {{cookiecutter.project_slug}}/templates/base.html:57
msgid "My Profile"
msgstr "Meu perfil"
#: {{cookiecutter.project_slug}}/users/admin.py:17
msgid "Personal info"
msgstr "Informação pessoal"
#: {{cookiecutter.project_slug}}/users/admin.py:19
msgid "Permissions"
msgstr "Permissões"
#: {{cookiecutter.project_slug}}/users/admin.py:30
msgid "Important dates"
msgstr "Datas importantes"
#: {{cookiecutter.project_slug}}/users/apps.py:7
msgid "Users"
msgstr "Usuários"
#: {{cookiecutter.project_slug}}/users/forms.py:24
#: {{cookiecutter.project_slug}}/users/tests/test_forms.py:36
msgid "This username has already been taken."
msgstr "Este nome de usuário já foi usado."
#: {{cookiecutter.project_slug}}/users/models.py:15
msgid "Name of User"
msgstr "Nome do Usuário"
#: {{cookiecutter.project_slug}}/users/views.py:23
msgid "Information successfully updated"
msgstr "Informação atualizada com sucesso"

View File

@ -25,7 +25,7 @@
"pixrem": "^5.0.0", "pixrem": "^5.0.0",
"postcss": "^8.3.11", "postcss": "^8.3.11",
"postcss-loader": "^7.0.2", "postcss-loader": "^7.0.2",
"postcss-preset-env": "^8.0.1", "postcss-preset-env": "^9.0.0",
"sass": "^1.43.4", "sass": "^1.43.4",
"sass-loader": "^13.2.0", "sass-loader": "^13.2.0",
"webpack": "^5.65.0", "webpack": "^5.65.0",

View File

@ -90,3 +90,23 @@ generated-members = [
"save", "save",
"delete", "delete",
] ]
# ==== djLint ====
[tool.djlint]
blank_line_after_tag = "load,extends"
close_void_tags = true
format_css = true
format_js = true
# TODO: remove T002 when fixed https://github.com/Riverside-Healthcare/djLint/issues/687
ignore = "H006,H030,H031,T002"
include = "H017,H035"
indent = 2
max_line_length = 119
profile = "django"
[tool.djlint.css]
indent_size = 2
[tool.djlint.js]
indent_size = 2

View File

@ -9,17 +9,17 @@ rcssmin==1.1.1 # https://github.com/ndparker/rcssmin
{%- endif %} {%- endif %}
argon2-cffi==21.3.0 # https://github.com/hynek/argon2_cffi argon2-cffi==21.3.0 # https://github.com/hynek/argon2_cffi
{%- if cookiecutter.use_whitenoise == 'y' %} {%- if cookiecutter.use_whitenoise == 'y' %}
whitenoise==6.4.0 # https://github.com/evansd/whitenoise whitenoise==6.5.0 # https://github.com/evansd/whitenoise
{%- endif %} {%- endif %}
redis==4.5.4 # https://github.com/redis/redis-py redis==4.6.0 # https://github.com/redis/redis-py
{%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %} {%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %}
hiredis==2.2.2 # https://github.com/redis/hiredis-py hiredis==2.2.3 # https://github.com/redis/hiredis-py
{%- endif %} {%- endif %}
{%- if cookiecutter.use_celery == "y" %} {%- if cookiecutter.use_celery == "y" %}
celery==5.2.7 # pyup: < 6.0 # https://github.com/celery/celery celery==5.3.1 # pyup: < 6.0 # https://github.com/celery/celery
django-celery-beat==2.5.0 # https://github.com/celery/django-celery-beat django-celery-beat==2.5.0 # https://github.com/celery/django-celery-beat
{%- if cookiecutter.use_docker == 'y' %} {%- if cookiecutter.use_docker == 'y' %}
flower==1.2.0 # https://github.com/mher/flower flower==2.0.0 # https://github.com/mher/flower
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
{%- if cookiecutter.use_async == 'y' %} {%- if cookiecutter.use_async == 'y' %}
@ -28,23 +28,23 @@ uvicorn[standard]==0.22.0 # https://github.com/encode/uvicorn
# Django # Django
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
django==4.1.9 # pyup: < 4.2 # https://www.djangoproject.com/ django==4.2.3 # pyup: < 5.0 # https://www.djangoproject.com/
django-environ==0.10.0 # https://github.com/joke2k/django-environ django-environ==0.10.0 # https://github.com/joke2k/django-environ
django-model-utils==4.3.1 # https://github.com/jazzband/django-model-utils django-model-utils==4.3.1 # https://github.com/jazzband/django-model-utils
django-allauth==0.54.0 # https://github.com/pennersr/django-allauth django-allauth==0.54.0 # https://github.com/pennersr/django-allauth
django-crispy-forms==2.0 # https://github.com/django-crispy-forms/django-crispy-forms django-crispy-forms==2.0 # https://github.com/django-crispy-forms/django-crispy-forms
crispy-bootstrap5==0.7 # https://github.com/django-crispy-forms/crispy-bootstrap5 crispy-bootstrap5==0.7 # https://github.com/django-crispy-forms/crispy-bootstrap5
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %} {%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
django-compressor==4.3.1 # https://github.com/django-compressor/django-compressor django-compressor==4.4 # https://github.com/django-compressor/django-compressor
{%- endif %} {%- endif %}
django-redis==5.2.0 # https://github.com/jazzband/django-redis django-redis==5.3.0 # https://github.com/jazzband/django-redis
{%- if cookiecutter.use_drf == 'y' %} {%- if cookiecutter.use_drf == 'y' %}
# Django REST Framework # Django REST Framework
djangorestframework==3.14.0 # https://github.com/encode/django-rest-framework djangorestframework==3.14.0 # https://github.com/encode/django-rest-framework
django-cors-headers==4.0.0 # https://github.com/adamchainz/django-cors-headers django-cors-headers==4.1.0 # https://github.com/adamchainz/django-cors-headers
# DRF-spectacular for api documentation # DRF-spectacular for api documentation
drf-spectacular==0.26.2 # https://github.com/tfranzel/drf-spectacular drf-spectacular==0.26.3 # https://github.com/tfranzel/drf-spectacular
{%- endif %} {%- endif %}
{%- if cookiecutter.frontend_pipeline == 'Webpack' %} {%- if cookiecutter.frontend_pipeline == 'Webpack' %}
django-webpack-loader==2.0.0 # https://github.com/django-webpack/django-webpack-loader django-webpack-loader==2.0.1 # https://github.com/django-webpack/django-webpack-loader
{%- endif %} {%- endif %}

View File

@ -1,11 +1,11 @@
-r base.txt -r base.txt
Werkzeug[watchdog]==2.3.4 # https://github.com/pallets/werkzeug Werkzeug[watchdog]==2.3.6 # https://github.com/pallets/werkzeug
ipdb==0.13.13 # https://github.com/gotcha/ipdb ipdb==0.13.13 # https://github.com/gotcha/ipdb
{%- if cookiecutter.use_docker == 'y' %} {%- if cookiecutter.use_docker == 'y' %}
psycopg2==2.9.6 # https://github.com/psycopg/psycopg2 psycopg[c]==3.1.9 # https://github.com/psycopg/psycopg
{%- else %} {%- else %}
psycopg2-binary==2.9.6 # https://github.com/psycopg/psycopg2 psycopg[binary]==3.1.9 # https://github.com/psycopg/psycopg
{%- endif %} {%- endif %}
{%- if cookiecutter.use_async == 'y' or cookiecutter.use_celery == 'y' %} {%- if cookiecutter.use_async == 'y' or cookiecutter.use_celery == 'y' %}
watchfiles==0.19.0 # https://github.com/samuelcolvin/watchfiles watchfiles==0.19.0 # https://github.com/samuelcolvin/watchfiles
@ -13,12 +13,12 @@ watchfiles==0.19.0 # https://github.com/samuelcolvin/watchfiles
# Testing # Testing
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
mypy==1.2.0 # https://github.com/python/mypy mypy==1.4.1 # https://github.com/python/mypy
django-stubs==4.2.0 # https://github.com/typeddjango/django-stubs django-stubs==4.2.3 # https://github.com/typeddjango/django-stubs
pytest==7.3.1 # https://github.com/pytest-dev/pytest pytest==7.4.0 # https://github.com/pytest-dev/pytest
pytest-sugar==0.9.7 # https://github.com/Frozenball/pytest-sugar pytest-sugar==0.9.7 # https://github.com/Frozenball/pytest-sugar
{%- if cookiecutter.use_drf == "y" %} {%- if cookiecutter.use_drf == "y" %}
djangorestframework-stubs==3.14.0 # https://github.com/typeddjango/djangorestframework-stubs djangorestframework-stubs==3.14.2 # https://github.com/typeddjango/djangorestframework-stubs
{%- endif %} {%- endif %}
# Documentation # Documentation
@ -30,19 +30,20 @@ sphinx-autobuild==2021.3.14 # https://github.com/GaretJax/sphinx-autobuild
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
flake8==6.0.0 # https://github.com/PyCQA/flake8 flake8==6.0.0 # https://github.com/PyCQA/flake8
flake8-isort==6.0.0 # https://github.com/gforcada/flake8-isort flake8-isort==6.0.0 # https://github.com/gforcada/flake8-isort
coverage==7.2.5 # https://github.com/nedbat/coveragepy coverage==7.2.7 # https://github.com/nedbat/coveragepy
black==23.3.0 # https://github.com/psf/black black==23.3.0 # https://github.com/psf/black
djlint==1.31.1 # https://github.com/Riverside-Healthcare/djLint
pylint-django==2.5.3 # https://github.com/PyCQA/pylint-django pylint-django==2.5.3 # https://github.com/PyCQA/pylint-django
{%- if cookiecutter.use_celery == 'y' %} {%- if cookiecutter.use_celery == 'y' %}
pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery
{%- endif %} {%- endif %}
pre-commit==3.3.2 # https://github.com/pre-commit/pre-commit pre-commit==3.3.3 # https://github.com/pre-commit/pre-commit
# Django # Django
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
factory-boy==3.2.1 # https://github.com/FactoryBoy/factory_boy factory-boy==3.2.1 # https://github.com/FactoryBoy/factory_boy
django-debug-toolbar==4.0.0 # https://github.com/jazzband/django-debug-toolbar django-debug-toolbar==4.1.0 # https://github.com/jazzband/django-debug-toolbar
django-extensions==3.2.1 # https://github.com/django-extensions/django-extensions django-extensions==3.2.3 # https://github.com/django-extensions/django-extensions
django-coverage-plugin==3.0.0 # https://github.com/nedbat/django_coverage_plugin django-coverage-plugin==3.0.0 # https://github.com/nedbat/django_coverage_plugin
pytest-django==4.5.2 # https://github.com/pytest-dev/pytest-django pytest-django==4.5.2 # https://github.com/pytest-dev/pytest-django

View File

@ -3,15 +3,15 @@
-r base.txt -r base.txt
gunicorn==20.1.0 # https://github.com/benoitc/gunicorn gunicorn==20.1.0 # https://github.com/benoitc/gunicorn
psycopg2==2.9.6 # https://github.com/psycopg/psycopg2 psycopg[c]==3.1.9 # https://github.com/psycopg/psycopg
{%- if cookiecutter.use_whitenoise == 'n' %} {%- if cookiecutter.use_whitenoise == 'n' %}
Collectfast==2.2.0 # https://github.com/antonagestam/collectfast Collectfast==2.2.0 # https://github.com/antonagestam/collectfast
{%- endif %} {%- endif %}
{%- if cookiecutter.use_sentry == "y" %} {%- if cookiecutter.use_sentry == "y" %}
sentry-sdk==1.24.0 # https://github.com/getsentry/sentry-python sentry-sdk==1.27.0 # https://github.com/getsentry/sentry-python
{%- endif %} {%- endif %}
{%- if cookiecutter.use_docker == "n" and cookiecutter.windows == "y" %} {%- if cookiecutter.use_docker == "n" and cookiecutter.windows == "y" %}
hiredis==2.2.2 # https://github.com/redis/hiredis-py hiredis==2.2.3 # https://github.com/redis/hiredis-py
{%- endif %} {%- endif %}
# Django # Django
@ -24,21 +24,21 @@ django-storages[google]==1.13.2 # https://github.com/jschneier/django-storages
django-storages[azure]==1.13.2 # https://github.com/jschneier/django-storages django-storages[azure]==1.13.2 # https://github.com/jschneier/django-storages
{%- endif %} {%- endif %}
{%- if cookiecutter.mail_service == 'Mailgun' %} {%- if cookiecutter.mail_service == 'Mailgun' %}
django-anymail[mailgun]==9.2 # https://github.com/anymail/django-anymail django-anymail[mailgun]==10.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Amazon SES' %} {%- elif cookiecutter.mail_service == 'Amazon SES' %}
django-anymail[amazon_ses]==9.2 # https://github.com/anymail/django-anymail django-anymail[amazon-ses]==10.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Mailjet' %} {%- elif cookiecutter.mail_service == 'Mailjet' %}
django-anymail[mailjet]==9.2 # https://github.com/anymail/django-anymail django-anymail[mailjet]==10.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Mandrill' %} {%- elif cookiecutter.mail_service == 'Mandrill' %}
django-anymail[mandrill]==9.2 # https://github.com/anymail/django-anymail django-anymail[mandrill]==10.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Postmark' %} {%- elif cookiecutter.mail_service == 'Postmark' %}
django-anymail[postmark]==9.2 # https://github.com/anymail/django-anymail django-anymail[postmark]==10.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Sendgrid' %} {%- elif cookiecutter.mail_service == 'Sendgrid' %}
django-anymail[sendgrid]==9.2 # https://github.com/anymail/django-anymail django-anymail[sendgrid]==10.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'SendinBlue' %} {%- elif cookiecutter.mail_service == 'SendinBlue' %}
django-anymail[sendinblue]==9.2 # https://github.com/anymail/django-anymail django-anymail[sendinblue]==10.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'SparkPost' %} {%- elif cookiecutter.mail_service == 'SparkPost' %}
django-anymail[sparkpost]==9.2 # https://github.com/anymail/django-anymail django-anymail[sparkpost]==10.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Other SMTP' %} {%- elif cookiecutter.mail_service == 'Other SMTP' %}
django-anymail==9.2 # https://github.com/anymail/django-anymail django-anymail==10.0 # https://github.com/anymail/django-anymail
{%- endif %} {%- endif %}

View File

@ -1 +1 @@
python-3.11.3 python-3.11.4

View File

@ -1,10 +1,14 @@
{% raw %}{% extends "base.html" %} {% raw %}{% extends "base.html" %}
{% block title %}Forbidden (403){% endblock %} {% block title %}Forbidden (403){% endblock title %}
{% block content %} {% block content %}
<h1>Forbidden (403)</h1> <h1>Forbidden (403)</h1>
<p>
<p>{% if exception %}{{ exception }}{% else %}You're not allowed to access this page.{% endif %}</p> {% if exception %}
{{ exception }}
{% else %}
You're not allowed to access this page.
{% endif %}
</p>
{% endblock content %} {% endblock content %}
{%- endraw %} {%- endraw %}

View File

@ -1,10 +1,14 @@
{% raw %}{% extends "base.html" %} {% raw %}{% extends "base.html" %}
{% block title %}Page not found{% endblock %} {% block title %}Page not found{% endblock title %}
{% block content %} {% block content %}
<h1>Page not found</h1> <h1>Page not found</h1>
<p>
<p>{% if exception %}{{ exception }}{% else %}This is not the page you were looking for.{% endif %}</p> {% if exception %}
{{ exception }}
{% else %}
This is not the page you were looking for.
{% endif %}
</p>
{% endblock content %} {% endblock content %}
{%- endraw %} {%- endraw %}

View File

@ -1,12 +1,11 @@
{% raw %}{% extends "base.html" %} {% raw %}{% extends "base.html" %}
{% block title %}Server Error{% endblock %} {% block title %}Server Error{% endblock title %}
{% block content %} {% block content %}
<h1>Ooops!!! 500</h1> <h1>Ooops!!! 500</h1>
<h3>Looks like something went wrong!</h3>
<h3>Looks like something went wrong!</h3> <p>
We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing.
<p>We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing.</p> </p>
{% endblock content %} {% endblock content %}
{%- endraw %} {%- endraw %}

View File

@ -2,11 +2,11 @@
{% load i18n %} {% load i18n %}
{% block head_title %}{% translate "Account Inactive" %}{% endblock %} {% block head_title %}
{% translate "Account Inactive" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Account Inactive" %}</h1> <h1>{% translate "Account Inactive" %}</h1>
<p>{% translate "This account is inactive." %}</p>
<p>{% translate "This account is inactive." %}</p> {% endblock inner %}
{% endblock %}
{%- endraw %} {%- endraw %}

View File

@ -1,11 +1,14 @@
{% raw %}{% extends "base.html" %} {% raw %}{% extends "base.html" %}
{% block title %}{% block head_title %}{% endblock head_title %}{% endblock title %}
{% block title %}
{% block head_title %}
{% endblock head_title %}
{% endblock title %}
{% block content %} {% block content %}
<div class="row"> <div class="row">
<div class="col-md-6 offset-md-3"> <div class="col-md-6 offset-md-3">
{% block inner %}{% endblock %} {% block inner %}{% endblock inner %}
</div>
</div> </div>
</div> {% endblock content %}
{% endblock %}
{%- endraw %} {%- endraw %}

View File

@ -4,76 +4,77 @@
{% load i18n %} {% load i18n %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block head_title %}{% translate "Account" %}{% endblock %} {% block head_title %}
{% translate "Account" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "E-mail Addresses" %}</h1> <h1>{% translate "E-mail Addresses" %}</h1>
{% if user.emailaddress_set.all %}
{% if user.emailaddress_set.all %} <p>{% translate "The following e-mail addresses are associated with your account:" %}</p>
<p>{% translate 'The following e-mail addresses are associated with your account:' %}</p> <form action="{% url 'account_email' %}" class="email_list" method="post">
{% csrf_token %}
<form action="{% url 'account_email' %}" class="email_list" method="post"> <fieldset class="blockLabels">
{% csrf_token %} {% for emailaddress in user.emailaddress_set.all %}
<fieldset class="blockLabels"> <div class="radio">
<label for="email_radio_{{ forloop.counter }}"
{% for emailaddress in user.emailaddress_set.all %} class="{% if emailaddress.primary %}primary_email{% endif %}">
<div class="radio"> <input id="email_radio_{{ forloop.counter }}"
<label for="email_radio_{{forloop.counter}}" class="{% if emailaddress.primary %}primary_email{%endif%}"> type="radio"
name="email"
<input id="email_radio_{{forloop.counter}}" type="radio" name="email" {% if emailaddress.primary or user.emailaddress_set.count == 1 %}checked="checked"{%endif %} value="{{emailaddress.email}}"/> {% if emailaddress.primary or user.emailaddress_set.count == 1 %}checked="checked"{% endif %}
value="{{ emailaddress.email }}" />
{{ emailaddress.email }} {{ emailaddress.email }}
{% if emailaddress.verified %} {% if emailaddress.verified %}
<span class="verified">{% translate "Verified" %}</span> <span class="verified">{% translate "Verified" %}</span>
{% else %} {% else %}
<span class="unverified">{% translate "Unverified" %}</span> <span class="unverified">{% translate "Unverified" %}</span>
{% endif %} {% endif %}
{% if emailaddress.primary %}<span class="primary">{% translate "Primary" %}</span>{% endif %} {% if emailaddress.primary %}
</label> <span class="primary">{% translate "Primary" %}</span>
</div> {% endif %}
{% endfor %} </label>
</div>
<div class="form-group"> {% endfor %}
<button class="secondaryAction btn btn-primary" type="submit" name="action_primary" >{% translate 'Make Primary' %}</button> <div class="form-group">
<button class="secondaryAction btn btn-primary" type="submit" name="action_send" >{% translate 'Re-send Verification' %}</button> <button class="secondaryAction btn btn-primary"
<button class="primaryAction btn btn-primary" type="submit" name="action_remove" >{% translate 'Remove' %}</button> type="submit"
</div> name="action_primary">{% translate "Make Primary" %}</button>
<button class="secondaryAction btn btn-primary"
</fieldset> type="submit"
</form> name="action_send">{% translate "Re-send Verification" %}</button>
<button class="primaryAction btn btn-primary"
{% else %} type="submit"
<p><strong>{% translate 'Warning:'%}</strong> {% translate "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}</p> name="action_remove">{% translate "Remove" %}</button>
</div>
{% endif %} </fieldset>
<h2>{% translate "Add E-mail Address" %}</h2>
<form method="post" action="{% url 'account_email' %}" class="add_email">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary" name="action_add" type="submit">{% translate "Add E-mail" %}</button>
</form> </form>
{% else %}
{% endblock %} <p>
<strong>{% translate "Warning:" %}</strong> {% translate "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}
</p>
{% endif %}
<h2>{% translate "Add E-mail Address" %}</h2>
<form method="post" action="{% url 'account_email' %}" class="add_email">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary" name="action_add" type="submit">{% translate "Add E-mail" %}</button>
</form>
{% endblock inner %}
{% block inline_javascript %} {% block inline_javascript %}
{{ block.super }} {{ block.super }}
<script type="text/javascript"> <script type="text/javascript">
window.addEventListener('DOMContentLoaded',function() { window.addEventListener('DOMContentLoaded', function() {
const message = "{% translate 'Do you really want to remove the selected e-mail address?' %}"; const message = "{% translate 'Do you really want to remove the selected e-mail address?' %}";
const actions = document.getElementsByName('action_remove'); const actions = document.getElementsByName('action_remove');
if (actions.length) { if (actions.length) {
actions[0].addEventListener("click",function(e) { actions[0].addEventListener("click", function(e) {
if (!confirm(message)) { if (!confirm(message)) {
e.preventDefault(); e.preventDefault();
}
});
} }
Array.from(document.getElementsByClassName('form-group')).forEach(x => x.classList.remove('row'));
}); });
} </script>
Array.from(document.getElementsByClassName('form-group')).forEach(x => x.classList.remove('row')); {% endblock inline_javascript %}
});
</script>
{% endblock %}
{%- endraw %} {%- endraw %}

View File

@ -3,30 +3,26 @@
{% load i18n %} {% load i18n %}
{% load account %} {% load account %}
{% block head_title %}{% translate "Confirm E-mail Address" %}{% endblock %} {% block head_title %}
{% translate "Confirm E-mail Address" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Confirm E-mail Address" %}</h1> <h1>{% translate "Confirm E-mail Address" %}</h1>
{% if confirmation %}
{% if confirmation %} {% user_display confirmation.email_address.user as user_display %}
<p>
{% user_display confirmation.email_address.user as user_display %} {% blocktranslate with confirmation.email_address.email as email %}Please confirm that <a href="mailto:{{ email }}">{{ email }}</a> is an e-mail address for user {{ user_display }}.{% endblocktranslate %}
</p>
<p>{% blocktranslate with confirmation.email_address.email as email %}Please confirm that <a href="mailto:{{ email }}">{{ email }}</a> is an e-mail address for user {{ user_display }}.{% endblocktranslate %}</p> <form method="post"
action="{% url 'account_confirm_email' confirmation.key %}">
<form method="post" action="{% url 'account_confirm_email' confirmation.key %}"> {% csrf_token %}
{% csrf_token %} <button class="btn btn-primary" type="submit">{% translate "Confirm" %}</button>
<button class="btn btn-primary" type="submit">{% translate 'Confirm' %}</button> </form>
</form> {% else %}
{% url 'account_email' as email_url %}
{% else %} <p>
{% blocktranslate %}This e-mail confirmation link expired or is invalid. Please <a href="{{ email_url }}">issue a new e-mail confirmation request</a>.{% endblocktranslate %}
{% url 'account_email' as email_url %} </p>
{% endif %}
<p>{% blocktranslate %}This e-mail confirmation link expired or is invalid. Please <a href="{{ email_url }}">issue a new e-mail confirmation request</a>.{% endblocktranslate %}</p> {% endblock inner %}
{% endif %}
{% endblock %}
{%- endraw %} {%- endraw %}

View File

@ -4,57 +4,50 @@
{% load account socialaccount %} {% load account socialaccount %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block head_title %}{% translate "Sign In" %}{% endblock %} {% block head_title %}
{% translate "Sign In" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Sign In" %}</h1>
<h1>{% translate "Sign In" %}</h1> {% get_providers as socialaccount_providers %}
{% if socialaccount_providers %}
{% get_providers as socialaccount_providers %}
{% if socialaccount_providers %}
<p>
{% translate "Please sign in with one of your existing third party accounts:" %}
{% if ACCOUNT_ALLOW_REGISTRATION %}
{% blocktranslate trimmed %}
Or, <a href="{{ signup_url }}">sign up</a>
for a {{ site_name }} account and sign in below:
{% endblocktranslate %}
{% endif %}
</p>
<div class="socialaccount_ballot">
<ul class="socialaccount_providers">
{% include "socialaccount/snippets/provider_list.html" with process="login" %}
</ul>
<div class="login-or">{% translate "or" %}</div>
</div>
{% include "socialaccount/snippets/login_extra.html" %}
{% else %}
{% if ACCOUNT_ALLOW_REGISTRATION %}
<p> <p>
{% blocktranslate trimmed %} {% translate "Please sign in with one of your existing third party accounts:" %}
If you have not created an account yet, then please {% if ACCOUNT_ALLOW_REGISTRATION %}
<a href="{{ signup_url }}">sign up</a> first. {% blocktranslate trimmed %}
{% endblocktranslate %} Or, <a href="{{ signup_url }}">sign up</a>
for a {{ site_name }} account and sign in below:
{% endblocktranslate %}
{% endif %}
</p> </p>
<div class="socialaccount_ballot">
<ul class="socialaccount_providers">
{% include "socialaccount/snippets/provider_list.html" with process="login" %}
</ul>
<div class="login-or">{% translate "or" %}</div>
</div>
{% include "socialaccount/snippets/login_extra.html" %}
{% else %}
{% if ACCOUNT_ALLOW_REGISTRATION %}
<p>
{% blocktranslate trimmed %}
If you have not created an account yet, then please
<a href="{{ signup_url }}">sign up</a> first.
{% endblocktranslate %}
</p>
{% endif %}
{% endif %} {% endif %}
{% endif %} <form class="login" method="post" action="{% url 'account_login' %}">
{% csrf_token %}
<form class="login" method="POST" action="{% url 'account_login' %}"> {{ form|crispy }}
{% csrf_token %} {% if redirect_field_value %}
{{ form|crispy }} <input type="hidden"
{% if redirect_field_value %} name="{{ redirect_field_name }}"
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" /> value="{{ redirect_field_value }}" />
{% endif %} {% endif %}
<a class="button secondaryAction" href="{% url 'account_reset_password' %}">{% translate "Forgot Password?" %}</a> <a class="button secondaryAction"
<button class="primaryAction btn btn-primary" type="submit">{% translate "Sign In" %}</button> href="{% url 'account_reset_password' %}">{% translate "Forgot Password?" %}</a>
</form> <button class="primaryAction btn btn-primary" type="submit">{% translate "Sign In" %}</button>
</form>
{% endblock %} {% endblock inner %}
{%- endraw %} {%- endraw %}

View File

@ -2,19 +2,20 @@
{% load i18n %} {% load i18n %}
{% block head_title %}{% translate "Sign Out" %}{% endblock %} {% block head_title %}
{% translate "Sign Out" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Sign Out" %}</h1> <h1>{% translate "Sign Out" %}</h1>
<p>{% translate "Are you sure you want to sign out?" %}</p>
<p>{% translate 'Are you sure you want to sign out?' %}</p> <form method="post" action="{% url 'account_logout' %}">
{% csrf_token %}
<form method="post" action="{% url 'account_logout' %}"> {% if redirect_field_value %}
{% csrf_token %} <input type="hidden"
{% if redirect_field_value %} name="{{ redirect_field_name }}"
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}"/> value="{{ redirect_field_value }}" />
{% endif %} {% endif %}
<button class="btn btn-danger" type="submit">{% translate 'Sign Out' %}</button> <button class="btn btn-danger" type="submit">{% translate "Sign Out" %}</button>
</form> </form>
{% endblock %} {% endblock inner %}
{%- endraw %} {%- endraw %}

View File

@ -3,15 +3,17 @@
{% load i18n %} {% load i18n %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block head_title %}{% translate "Change Password" %}{% endblock %} {% block head_title %}
{% translate "Change Password" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Change Password" %}</h1> <h1>{% translate "Change Password" %}</h1>
<form method="post"
<form method="POST" action="{% url 'account_change_password' %}" class="password_change"> action="{% url 'account_change_password' %}"
{% csrf_token %} class="password_change">
{{ form|crispy }} {% csrf_token %}
<button class="btn btn-primary" type="submit" name="action">{% translate "Change Password" %}</button> {{ form|crispy }}
</form> <button class="btn btn-primary" type="submit" name="action">{% translate "Change Password" %}</button>
{% endblock %} </form>
{% endblock inner %}
{%- endraw %} {%- endraw %}

View File

@ -4,23 +4,26 @@
{% load account %} {% load account %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block head_title %}{% translate "Password Reset" %}{% endblock %} {% block head_title %}
{% translate "Password Reset" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Password Reset" %}</h1>
<h1>{% translate "Password Reset" %}</h1> {% if user.is_authenticated %}
{% if user.is_authenticated %}
{% include "account/snippets/already_logged_in.html" %} {% include "account/snippets/already_logged_in.html" %}
{% endif %} {% endif %}
<p>
<p>{% translate "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}</p> {% translate "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}
</p>
<form method="POST" action="{% url 'account_reset_password' %}" class="password_reset"> <form method="post"
{% csrf_token %} action="{% url 'account_reset_password' %}"
{{ form|crispy }} class="password_reset">
<input class="btn btn-primary" type="submit" value="{% translate 'Reset My Password' %}" /> {% csrf_token %}
</form> {{ form|crispy }}
<input class="btn btn-primary"
<p>{% blocktranslate %}Please contact us if you have any trouble resetting your password.{% endblocktranslate %}</p> type="submit"
{% endblock %} value="{% translate 'Reset My Password' %}" />
</form>
<p>{% blocktranslate %}Please contact us if you have any trouble resetting your password.{% endblocktranslate %}</p>
{% endblock inner %}
{%- endraw %} {%- endraw %}

View File

@ -3,15 +3,16 @@
{% load i18n %} {% load i18n %}
{% load account %} {% load account %}
{% block head_title %}{% translate "Password Reset" %}{% endblock %} {% block head_title %}
{% translate "Password Reset" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Password Reset" %}</h1> <h1>{% translate "Password Reset" %}</h1>
{% if user.is_authenticated %}
{% if user.is_authenticated %}
{% include "account/snippets/already_logged_in.html" %} {% include "account/snippets/already_logged_in.html" %}
{% endif %} {% endif %}
<p>
<p>{% blocktranslate %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}</p> {% blocktranslate %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}
{% endblock %} </p>
{% endblock inner %}
{%- endraw %} {%- endraw %}

View File

@ -2,24 +2,36 @@
{% load i18n %} {% load i18n %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block head_title %}{% translate "Change Password" %}{% endblock %}
{% block head_title %}
{% translate "Change Password" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% if token_fail %}{% translate "Bad Token" %}{% else %}{% translate "Change Password" %}{% endif %}</h1> <h1>
{% if token_fail %} {% if token_fail %}
{% url 'account_reset_password' as passwd_reset_url %} {% translate "Bad Token" %}
<p>{% blocktranslate %}The password reset link was invalid, possibly because it has already been used. Please request a <a href="{{ passwd_reset_url }}">new password reset</a>.{% endblocktranslate %}</p>
{% else %} {% else %}
{% if form %} {% translate "Change Password" %}
<form method="POST" action=".">
{% csrf_token %}
{{ form|crispy }}
<input class="btn btn-primary" type="submit" name="action" value="{% translate 'change password' %}"/>
</form>
{% else %}
<p>{% translate 'Your password is now changed.' %}</p>
{% endif %}
{% endif %} {% endif %}
{% endblock %} </h1>
{% if token_fail %}
{% url 'account_reset_password' as passwd_reset_url %}
<p>
{% blocktranslate %}The password reset link was invalid, possibly because it has already been used. Please request a <a href="{{ passwd_reset_url }}">new password reset</a>.{% endblocktranslate %}
</p>
{% else %}
{% if form %}
<form method="post" action=".">
{% csrf_token %}
{{ form|crispy }}
<input class="btn btn-primary"
type="submit"
name="action"
value="{% translate 'change password' %}" />
</form>
{% else %}
<p>{% translate "Your password is now changed." %}</p>
{% endif %}
{% endif %}
{% endblock inner %}
{%- endraw %} {%- endraw %}

View File

@ -1,10 +1,12 @@
{% raw %}{% extends "account/base.html" %} {% raw %}{% extends "account/base.html" %}
{% load i18n %} {% load i18n %}
{% block head_title %}{% translate "Change Password" %}{% endblock %}
{% block head_title %}
{% translate "Change Password" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Change Password" %}</h1> <h1>{% translate "Change Password" %}</h1>
<p>{% translate 'Your password is now changed.' %}</p> <p>{% translate "Your password is now changed." %}</p>
{% endblock %} {% endblock inner %}
{%- endraw %} {%- endraw %}

View File

@ -3,15 +3,20 @@
{% load i18n %} {% load i18n %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block head_title %}{% translate "Set Password" %}{% endblock %} {% block head_title %}
{% translate "Set Password" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Set Password" %}</h1> <h1>{% translate "Set Password" %}</h1>
<form method="post"
<form method="POST" action="{% url 'account_set_password' %}" class="password_set"> action="{% url 'account_set_password' %}"
{% csrf_token %} class="password_set">
{{ form|crispy }} {% csrf_token %}
<input class="btn btn-primary" type="submit" name="action" value="{% translate 'Set Password' %}"/> {{ form|crispy }}
</form> <input class="btn btn-primary"
{% endblock %} type="submit"
name="action"
value="{% translate 'Set Password' %}" />
</form>
{% endblock inner %}
{%- endraw %} {%- endraw %}

View File

@ -3,21 +3,26 @@
{% load i18n %} {% load i18n %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block head_title %}{% translate "Signup" %}{% endblock %} {% block head_title %}
{% translate "Signup" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Sign Up" %}</h1> <h1>{% translate "Sign Up" %}</h1>
<p>
<p>{% blocktranslate %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktranslate %}</p> {% blocktranslate %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktranslate %}
</p>
<form class="signup" id="signup_form" method="post" action="{% url 'account_signup' %}"> <form class="signup"
{% csrf_token %} id="signup_form"
{{ form|crispy }} method="post"
{% if redirect_field_value %} action="{% url 'account_signup' %}">
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" /> {% csrf_token %}
{% endif %} {{ form|crispy }}
<button class="btn btn-primary" type="submit">{% translate "Sign Up" %} &raquo;</button> {% if redirect_field_value %}
</form> <input type="hidden"
name="{{ redirect_field_name }}"
{% endblock %} value="{{ redirect_field_value }}" />
{% endif %}
<button class="btn btn-primary" type="submit">{% translate "Sign Up" %} »</button>
</form>
{% endblock inner %}
{%- endraw %} {%- endraw %}

View File

@ -2,11 +2,11 @@
{% load i18n %} {% load i18n %}
{% block head_title %}{% translate "Sign Up Closed" %}{% endblock %} {% block head_title %}
{% translate "Sign Up Closed" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Sign Up Closed" %}</h1> <h1>{% translate "Sign Up Closed" %}</h1>
<p>{% translate "We are sorry, but the sign up is currently closed." %}</p>
<p>{% translate "We are sorry, but the sign up is currently closed." %}</p> {% endblock inner %}
{% endblock %}
{%- endraw %} {%- endraw %}

View File

@ -2,12 +2,13 @@
{% load i18n %} {% load i18n %}
{% block head_title %}{% translate "Verify Your E-mail Address" %}{% endblock %} {% block head_title %}
{% translate "Verify Your E-mail Address" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Verify Your E-mail Address" %}</h1> <h1>{% translate "Verify Your E-mail Address" %}</h1>
<p>
<p>{% blocktranslate %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}</p> {% blocktranslate %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}
</p>
{% endblock %} {% endblock inner %}
{%- endraw %} {%- endraw %}

View File

@ -2,21 +2,24 @@
{% load i18n %} {% load i18n %}
{% block head_title %}{% translate "Verify Your E-mail Address" %}{% endblock %} {% block head_title %}
{% translate "Verify Your E-mail Address" %}
{% endblock head_title %}
{% block inner %} {% block inner %}
<h1>{% translate "Verify Your E-mail Address" %}</h1> <h1>{% translate "Verify Your E-mail Address" %}</h1>
{% url 'account_email' as email_url %}
{% url 'account_email' as email_url %} <p>
{% blocktranslate %}This part of the site requires us to verify that
<p>{% blocktranslate %}This part of the site requires us to verify that
you are who you claim to be. For this purpose, we require that you you are who you claim to be. For this purpose, we require that you
verify ownership of your e-mail address. {% endblocktranslate %}</p> verify ownership of your e-mail address. {% endblocktranslate %}
</p>
<p>{% blocktranslate %}We have sent an e-mail to you for <p>
{% blocktranslate %}We have sent an e-mail to you for
verification. Please click on the link inside this e-mail. Please verification. Please click on the link inside this e-mail. Please
contact us if you do not receive it within a few minutes.{% endblocktranslate %}</p> contact us if you do not receive it within a few minutes.{% endblocktranslate %}
</p>
<p>{% blocktranslate %}<strong>Note:</strong> you can still <a href="{{ email_url }}">change your e-mail address</a>.{% endblocktranslate %}</p> <p>
{% endblock %} {% blocktranslate %}<strong>Note:</strong> you can still <a href="{{ email_url }}">change your e-mail address</a>.{% endblocktranslate %}
</p>
{% endblock inner %}
{%- endraw %} {%- endraw %}

View File

@ -1,150 +1,194 @@
{% raw %}{% load static i18n {% endraw %} {% raw %}
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}compress {% load static i18n {% endraw %}
{%- endif %}{% raw %}%}{% endraw %}
{%- if cookiecutter.frontend_pipeline == 'Webpack' %}{% raw %}{% load render_bundle from webpack_loader %}{% endraw %} {%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}compress{%- endif %}{% raw %}%}{% endraw %}
{%- if cookiecutter.frontend_pipeline == 'Webpack' %}{% raw %}
{% load render_bundle from webpack_loader %}
{% endraw %}
{%- endif %}{% raw %}<!DOCTYPE html> {%- endif %}{% raw %}<!DOCTYPE html>
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
<html lang="{{ LANGUAGE_CODE }}"> <html lang="{{ LANGUAGE_CODE }}">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge"> <meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>{% block title %}{% endraw %}{{ cookiecutter.project_name }}{% raw %}{% endblock title %}</title> <title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> {% block title %}
<meta name="description" content="{% endraw %}{{ cookiecutter.description }}{% raw %}"> {% endraw %}{{ cookiecutter.project_name }}{% raw %}
<meta name="author" content="{% endraw %}{{ cookiecutter.author_name }}{% raw %}"> {% endblock title %}
</title>
<link rel="icon" href="{% static 'images/favicons/favicon.ico' %}"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description"
{% block css %} content="{% endraw %}{{ cookiecutter.description }}{% raw %}" />
{%- endraw %} <meta name="author"
{%- if cookiecutter.frontend_pipeline in ['None', 'Django Compressor'] %} content="{% endraw %}{{ cookiecutter.author_name }}{% raw %}" />
<link rel="icon" href="{% static 'images/favicons/favicon.ico' %}" />
{% block css %}
{%- endraw %}
{%- if cookiecutter.frontend_pipeline in ['None', 'Django Compressor'] %}
{%- raw %} {%- raw %}
<!-- Latest compiled and minified Bootstrap CSS --> <!-- Latest compiled and minified Bootstrap CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/css/bootstrap.min.css" integrity="sha512-SbiR/eusphKoMVVXysTKG/7VseWii+Y3FdHrt0EpKgpToZeemhqHeZeLWLhJutz/2ut2Vw1uQEj2MbRF+TVBUA==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <link rel="stylesheet"
{%- endraw %} href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/css/bootstrap.min.css"
{%- endif %} integrity="sha512-SbiR/eusphKoMVVXysTKG/7VseWii+Y3FdHrt0EpKgpToZeemhqHeZeLWLhJutz/2ut2Vw1uQEj2MbRF+TVBUA=="
{%- raw %} crossorigin="anonymous"
<!-- Your stuff: Third-party CSS libraries go here --> referrerpolicy="no-referrer" />
{%- endraw %}
<!-- This file stores project-specific CSS --> {%- endif %}
{%- endraw %}{% if cookiecutter.frontend_pipeline == 'None' %}{% raw %} {%- raw %}
<link href="{% static 'css/project.css' %}" rel="stylesheet"> <!-- Your stuff: Third-party CSS libraries go here -->
{%- endraw %}{% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}{% raw %} <!-- This file stores project-specific CSS -->
{% compress css %} {%- endraw %}
<link href="{% static 'css/project.css' %}" rel="stylesheet"> {% if cookiecutter.frontend_pipeline == 'None' %}
{% endcompress %} {% raw %}
{%- endraw %}{% elif cookiecutter.frontend_pipeline == 'Gulp' %}{% raw %} <link href="{% static 'css/project.css' %}" rel="stylesheet" />
<link href="{% static 'css/project.min.css' %}" rel="stylesheet"> {%- endraw %}
{%- endraw %}{% elif cookiecutter.frontend_pipeline == "Webpack" %}{% raw %} {% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}
{% render_bundle 'project' 'css' %} {% raw %}
{%- endraw %}{% endif %}{% raw %} {% compress css %}
{% endblock %} <link href="{% static 'css/project.css' %}" rel="stylesheet" />
<!-- Le javascript {% endcompress %}
{%- endraw %}
{% elif cookiecutter.frontend_pipeline == 'Gulp' %}
{% raw %}
<link href="{% static 'css/project.min.css' %}" rel="stylesheet" />
{%- endraw %}
{% elif cookiecutter.frontend_pipeline == "Webpack" %}
{% raw %}
{% render_bundle 'project' 'css' %}
{%- endraw %}
{% endif %}
{% raw %}
{% endblock css %}
<!-- Le javascript
================================================== --> ================================================== -->
{# Placed at the top of the document so pages load faster with defer #} {# Placed at the top of the document so pages load faster with defer #}
{% block javascript %} {% block javascript %}
{%- endraw %}{% if cookiecutter.frontend_pipeline == 'Gulp' %}{% raw %} {%- endraw %}
<!-- Vendor dependencies bundled as one file --> {% if cookiecutter.frontend_pipeline == 'Gulp' %}
<script defer src="{% static 'js/vendors.min.js' %}"></script> {% raw %}
{%- endraw %}{% elif cookiecutter.frontend_pipeline == "Webpack" %}{% raw %} <!-- Vendor dependencies bundled as one file -->
<!-- Vendor dependencies bundled as one file --> <script defer src="{% static 'js/vendors.min.js' %}"></script>
{% render_bundle 'vendors' 'js' attrs='defer' %} {%- endraw %}
{%- endraw %}{% else %}{% raw %} {% elif cookiecutter.frontend_pipeline == "Webpack" %}
<!-- Bootstrap JS --> {% raw %}
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.min.js" integrity="sha512-1/RvZTcCDEUjY/CypiMz+iqqtaoQfAITmNSJY17Myp4Ms5mdxPS5UV7iOfdZoxcGhzFbOm6sntTKJppjvuhg4g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <!-- Vendor dependencies bundled as one file -->
<!-- Your stuff: Third-party javascript libraries go here --> {% render_bundle 'vendors' 'js' attrs='defer' %}
{%- endraw %}{% endif %}{% raw %} {%- endraw %}
{% else %}
<!-- place project specific Javascript in this file --> {% raw %}
{%- endraw %}{% if cookiecutter.frontend_pipeline == 'None' %}{% raw %} <!-- Bootstrap JS -->
<script defer src="{% static 'js/project.js' %}"></script> <script defer
{%- endraw %}{% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}{% raw %} src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.min.js"
{% compress js %} integrity="sha512-1/RvZTcCDEUjY/CypiMz+iqqtaoQfAITmNSJY17Myp4Ms5mdxPS5UV7iOfdZoxcGhzFbOm6sntTKJppjvuhg4g=="
<script defer src="{% static 'js/project.js' %}"></script> crossorigin="anonymous"
{% endcompress %} referrerpolicy="no-referrer"></script>
{%- endraw %}{% elif cookiecutter.frontend_pipeline == 'Gulp' %}{% raw %} <!-- Your stuff: Third-party javascript libraries go here -->
<script defer src="{% static 'js/project.min.js' %}"></script> {%- endraw %}
{%- endraw %}{% elif cookiecutter.frontend_pipeline == "Webpack" %}{% raw %} {% endif %}
{% render_bundle 'project' 'js' attrs='defer' %} {% raw %}
{%- endraw %}{% endif %}{% raw %} <!-- place project specific Javascript in this file -->
{%- endraw %}
{% endblock javascript %} {% if cookiecutter.frontend_pipeline == 'None' %}
{% raw %}
</head> <script defer src="{% static 'js/project.js' %}"></script>
{%- endraw %}
<body> {% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}
{% raw %}
<div class="mb-1"> {% compress js %}
<nav class="navbar navbar-expand-md navbar-light bg-light"> <script defer src="{% static 'js/project.js' %}"></script>
<div class="container-fluid"> {% endcompress %}
<button class="navbar-toggler navbar-toggler-right" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> {%- endraw %}
<span class="navbar-toggler-icon"></span> {% elif cookiecutter.frontend_pipeline == 'Gulp' %}
</button> {% raw %}
<a class="navbar-brand" href="{% url 'home' %}">{% endraw %}{{ cookiecutter.project_name }}{% raw %}</a> <script defer src="{% static 'js/project.min.js' %}"></script>
{%- endraw %}
<div class="collapse navbar-collapse" id="navbarSupportedContent"> {% elif cookiecutter.frontend_pipeline == "Webpack" %}
<ul class="navbar-nav mr-auto"> {% raw %}
<li class="nav-item active"> {% render_bundle 'project' 'js' attrs='defer' %}
<a class="nav-link" href="{% url 'home' %}">Home <span class="visually-hidden">(current)</span></a> {%- endraw %}
</li> {% endif %}
{% raw %}
{% endblock javascript %}
</head>
<body>
<div class="mb-1">
<nav class="navbar navbar-expand-md navbar-light bg-light">
<div class="container-fluid">
<button class="navbar-toggler navbar-toggler-right"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="{% url 'home' %}">{% endraw %}{{ cookiecutter.project_name }}{% raw %}</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="{% url 'home' %}">Home <span class="visually-hidden">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'about' %}">About</a>
</li>
{% if request.user.is_authenticated %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{% url 'about' %}">About</a> <a class="nav-link"
href="{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{% url 'users:detail' request.user.pk %}{% endraw %}{% else %}{% raw %}{% url 'users:detail' request.user.username %}{% endraw %}{% endif %}{% raw %}">{% translate "My Profile" %}</a>
</li> </li>
{% if request.user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{% url 'users:detail' request.user.pk %}{% endraw %}{% else %}{% raw %}{% url 'users:detail' request.user.username %}{% endraw %}{% endif %}{% raw %}">{% translate "My Profile" %}</a>
</li>
<li class="nav-item">
{# URL provided by django-allauth/account/urls.py #}
<a class="nav-link" href="{% url 'account_logout' %}">{% translate "Sign Out" %}</a>
</li>
{% else %}
{% if ACCOUNT_ALLOW_REGISTRATION %}
<li class="nav-item"> <li class="nav-item">
{# URL provided by django-allauth/account/urls.py #} {# URL provided by django-allauth/account/urls.py #}
<a id="sign-up-link" class="nav-link" href="{% url 'account_signup' %}">{% translate "Sign Up" %}</a> <a class="nav-link" href="{% url 'account_logout' %}">{% translate "Sign Out" %}</a>
</li> </li>
{% endif %} {% else %}
{% if ACCOUNT_ALLOW_REGISTRATION %}
<li class="nav-item"> <li class="nav-item">
{# URL provided by django-allauth/account/urls.py #} {# URL provided by django-allauth/account/urls.py #}
<a id="log-in-link" class="nav-link" href="{% url 'account_login' %}">{% translate "Sign In" %}</a> <a id="sign-up-link" class="nav-link" href="{% url 'account_signup' %}">{% translate "Sign Up" %}</a>
</li> </li>
{% endif %} {% endif %}
</ul> <li class="nav-item">
</div> {# URL provided by django-allauth/account/urls.py #}
<a id="log-in-link" class="nav-link" href="{% url 'account_login' %}">{% translate "Sign In" %}</a>
</li>
{% endif %}
</ul>
</div> </div>
</nav> </div>
</nav>
</div> </div>
<div class="container">
<div class="container"> {% if messages %}
{% for message in messages %}
{% if messages %} <div class="alert alert-dismissible {% if message.tags %}alert-{{ message.tags }}{% endif %}">
{% for message in messages %} {{ message }}
<div class="alert alert-dismissible {% if message.tags %}alert-{{ message.tags }}{% endif %}"> <button type="button"
{{ message }} class="btn-close"
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> data-bs-dismiss="alert"
</div> aria-label="Close"></button>
{% endfor %} </div>
{% endif %} {% endfor %}
{% endif %}
{% block content %} {% block content %}
<p>Use this document as a way to quick start any new project.</p> <p>Use this document as a way to quick start any new project.</p>
{% endblock content %} {% endblock content %}
</div>
</div> <!-- /container --> <!-- /container -->
{% block modal %}
{% block modal %}{% endblock modal %} {% endblock modal %}
{% block inline_javascript %}
{% block inline_javascript %}
{% comment %} {% comment %}
Script tags with only code, no src (defer by default). To run Script tags with only code, no src (defer by default). To run
with a "defer" so that you run inline code: with a "defer" so that you run inline code:
<script> <script>
window.addEventListener('DOMContentLoaded', () => {/* Run whatever you want */}); window.addEventListener('DOMContentLoaded', () => {
/* Run whatever you want */
});
</script> </script>
{% endcomment %} {% endcomment %}
{% endblock inline_javascript %} {% endblock inline_javascript %}
</body> </body>
</html> </html>
{%- endraw %} {%- endraw %}

View File

@ -1 +1,3 @@
{% raw %}{% extends "base.html" %}{% endraw %} {% raw %}{% extends "base.html" %}
{% endraw %}

View File

@ -1 +1,3 @@
{% raw %}{% extends "base.html" %}{% endraw %} {% raw %}{% extends "base.html" %}
{% endraw %}

View File

@ -1,35 +1,45 @@
{% raw %}{% extends "base.html" %} {% raw %}{% extends "base.html" %}
{% load static %} {% load static %}
{% block title %}User: {% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{{ object.name }}{% endraw %}{% else %}{% raw %}{{ object.username }}{% endraw %}{% endif %}{% raw %}{% endblock %} {% block title %}
User: {% endraw %}
{% if cookiecutter.username_type == "email" %}
{% raw %}{{ object.name }}{% endraw %}
{% else %}
{% raw %}{{ object.username }}{% endraw %}
{% endif %}
{% raw %}
{% endblock title %}
{% block content %} {% block content %}
<div class="container"> <div class="container">
<div class="row">
<div class="row"> <div class="col-sm-12">
<div class="col-sm-12"> <h2>
{% endraw %}
<h2>{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{{ object.name }}{% endraw %}{% else %}{% raw %}{{ object.username }}{% endraw %}{% endif %}{% raw %}</h2> {% if cookiecutter.username_type == "email" %}
{% if object.name %} {% raw %}{{ object.name }}{% endraw %}
<p>{{ object.name }}</p> {% else %}
{% endif %} {% raw %}{{ object.username }}{% endraw %}
{% endif %}
{% raw %}
</h2>
{% if object.name %}<p>{{ object.name }}</p>{% endif %}
</div> </div>
</div> </div>
{% if object == request.user %}
{% if object == request.user %} <!-- Action buttons -->
<!-- Action buttons --> <div class="row">
<div class="row"> <div class="col-sm-12">
<a class="btn btn-primary" href="{% url 'users:update' %}" role="button">My Info</a>
<div class="col-sm-12"> <a class="btn btn-primary"
<a class="btn btn-primary" href="{% url 'users:update' %}" role="button">My Info</a> href="{% url 'account_email' %}"
<a class="btn btn-primary" href="{% url 'account_email' %}" role="button">E-Mail</a> role="button">E-Mail</a>
<!-- Your Stuff: Custom user template urls --> <!-- Your Stuff: Custom user template urls -->
</div> </div>
</div>
</div> <!-- End Action buttons -->
<!-- End Action buttons --> {% endif %}
{% endif %}
</div> </div>
{% endblock content %} {% endblock content %}
{%- endraw %} {%- endraw %}

View File

@ -1,18 +1,36 @@
{% raw %}{% extends "base.html" %} {% raw %}{% extends "base.html" %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block title %}{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{{ user.name }}{% endraw %}{% else %}{% raw %}{{ user.username }}{% endraw %}{% endif %}{% raw %}{% endblock %} {% block title %}
{% endraw %}
{% if cookiecutter.username_type == "email" %}
{% raw %}{{ user.name }}{% endraw %}
{% else %}
{% raw %}{{ user.username }}{% endraw %}
{% endif %}
{% raw %}
{% endblock title %}
{% block content %} {% block content %}
<h1>{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{{ user.name }}{% endraw %}{% else %}{% raw %}{{ user.username }}{% endraw %}{% endif %}{% raw %}</h1> <h1>
<form class="form-horizontal" method="post" action="{% url 'users:update' %}"> {% endraw %}
{% csrf_token %} {% if cookiecutter.username_type == "email" %}
{{ form|crispy }} {% raw %}{{ user.name }}{% endraw %}
<div class="control-group"> {% else %}
<div class="controls"> {% raw %}{{ user.username }}{% endraw %}
<button type="submit" class="btn btn-primary">Update</button> {% endif %}
</div> {% raw %}
</h1>
<form class="form-horizontal"
method="post"
action="{% url 'users:update' %}">
{% csrf_token %}
{{ form|crispy }}
<div class="control-group">
<div class="controls">
<button type="submit" class="btn btn-primary">Update</button>
</div> </div>
</form> </div>
{% endblock %} </form>
{% endblock content %}
{%- endraw %} {%- endraw %}

View File

@ -1,16 +1,37 @@
from typing import Any from __future__ import annotations
import typing
from allauth.account.adapter import DefaultAccountAdapter from allauth.account.adapter import DefaultAccountAdapter
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
from django.conf import settings from django.conf import settings
from django.http import HttpRequest from django.http import HttpRequest
if typing.TYPE_CHECKING:
from allauth.socialaccount.models import SocialLogin
from {{cookiecutter.project_slug}}.users.models import User
class AccountAdapter(DefaultAccountAdapter): class AccountAdapter(DefaultAccountAdapter):
def is_open_for_signup(self, request: HttpRequest): def is_open_for_signup(self, request: HttpRequest) -> bool:
return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True) return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True)
class SocialAccountAdapter(DefaultSocialAccountAdapter): class SocialAccountAdapter(DefaultSocialAccountAdapter):
def is_open_for_signup(self, request: HttpRequest, sociallogin: Any): def is_open_for_signup(self, request: HttpRequest, sociallogin: SocialLogin) -> bool:
return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True) return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True)
def populate_user(self, request: HttpRequest, sociallogin: SocialLogin, data: dict[str, typing.Any]) -> User:
"""
Populates user information from social provider info.
See: https://django-allauth.readthedocs.io/en/latest/advanced.html?#creating-and-populating-user-instances
"""
user = sociallogin.user
if name := data.get("name"):
user.name = name
elif first_name := data.get("first_name"):
user.name = first_name
if last_name := data.get("last_name"):
user.name += f" {last_name}"
return super().populate_user(request, sociallogin, data)

View File

@ -1,12 +1,18 @@
from django.conf import settings
from django.contrib import admin from django.contrib import admin
from django.contrib.auth import admin as auth_admin from django.contrib.auth import admin as auth_admin
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model, decorators
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from {{ cookiecutter.project_slug }}.users.forms import UserAdminChangeForm, UserAdminCreationForm from {{ cookiecutter.project_slug }}.users.forms import UserAdminChangeForm, UserAdminCreationForm
User = get_user_model() User = get_user_model()
if settings.DJANGO_ADMIN_FORCE_ALLAUTH:
# Force the `admin` sign in process to go through the `django-allauth` workflow:
# https://django-allauth.readthedocs.io/en/stable/advanced.html#admin
admin.site.login = decorators.login_required(admin.site.login) # type: ignore[method-assign]
@admin.register(User) @admin.register(User)
class UserAdmin(auth_admin.UserAdmin): class UserAdmin(auth_admin.UserAdmin):

View File

@ -7,6 +7,7 @@ from django.contrib.sessions.middleware import SessionMiddleware
from django.http import HttpRequest, HttpResponseRedirect from django.http import HttpRequest, HttpResponseRedirect
from django.test import RequestFactory from django.test import RequestFactory
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from {{ cookiecutter.project_slug }}.users.forms import UserAdminChangeForm from {{ cookiecutter.project_slug }}.users.forms import UserAdminChangeForm
from {{ cookiecutter.project_slug }}.users.models import User from {{ cookiecutter.project_slug }}.users.models import User
@ -72,7 +73,7 @@ class TestUserUpdateView:
view.form_valid(form) view.form_valid(form)
messages_sent = [m.message for m in messages.get_messages(request)] messages_sent = [m.message for m in messages.get_messages(request)]
assert messages_sent == ["Information successfully updated"] assert messages_sent == [_("Information successfully updated")]
class TestUserRedirectView: class TestUserRedirectView: