diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 53a486671..23ca7a37f 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -2,11 +2,4 @@ github: [pydanny, browniebroke] patreon: feldroy -open_collective: # Replace with a single Open Collective username -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"] +open_collective: cookiecutter-django diff --git a/.github/contributors.json b/.github/contributors.json index 37c85e1bc..e08ce0b05 100644 --- a/.github/contributors.json +++ b/.github/contributors.json @@ -53,6 +53,12 @@ "twitter_username": "sfdye", "is_core": true }, + { + "name": "Jelmer Draaijer", + "github_login": "foarsitter", + "twitter_username": "", + "is_core": true + }, { "name": "18", "github_login": "dezoito", @@ -553,11 +559,6 @@ "github_login": "jvanbrug", "twitter_username": "" }, - { - "name": "Jelmer Draaijer", - "github_login": "foarsitter", - "twitter_username": "" - }, { "name": "Jerome Caisip", "github_login": "jeromecaisip", @@ -1392,5 +1393,20 @@ "name": "Birtibu", "github_login": "Birtibu", "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": "" } ] \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2c7876d3c..3acfca53d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,7 +23,7 @@ repos: args: ["--tab-width", "2"] - repo: https://github.com/asottile/pyupgrade - rev: v3.4.0 + rev: v3.8.0 hooks: - id: pyupgrade args: [--py311-plus] diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fcdedef9..53b4f635e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,258 @@ All enhancements and patches to Cookiecutter Django will be documented in this f +## 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>=2.0.0 js library required after upgrade django-webpack-loader>=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 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 340588a9a..184d445d5 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -74,6 +74,13 @@ accept and merge pull requests. sfdye + + Jelmer Draaijer + + foarsitter + + + _Audrey is also the creator of Cookiecutter. Audrey and Daniel are on @@ -1006,13 +1013,6 @@ Listed in alphabetical order. - - Jelmer Draaijer - - foarsitter - - - Jens Nilsson @@ -1069,6 +1069,13 @@ Listed in alphabetical order. + + Joseph Hanna + + sanchimenea + + + jugglinmike @@ -1307,6 +1314,13 @@ Listed in alphabetical order. + + masavini + + masavini + + + Mateusz Ostaszewski @@ -1314,6 +1328,13 @@ Listed in alphabetical order. + + Matheus Jardim Bernardes + + matheusjardimb + + + Mathijs Hoogland diff --git a/README.md b/README.md index d718ee34c..0a39fb084 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ production-ready Django projects quickly. ## Features -- For Django 4.1 +- For Django 4.2 - Works with Python 3.11 - Renders Django projects with 100% starting test coverage - Twitter [Bootstrap](https://github.com/twbs/bootstrap) v5 @@ -51,15 +51,16 @@ _These features can be enabled during initial project setup._ ## Constraints - 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). ## 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. - 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. 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 timezone [UTC]: America/Los_Angeles 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 Select postgresql_version: - 1 - 14 - 2 - 13 - 3 - 12 - 4 - 11 - 5 - 10 + 1 - 15 + 2 - 14 + 3 - 13 + 4 - 12 + 5 - 11 + 6 - 10 Choose from 1, 2, 3, 4, 5 [1]: 1 Select cloud_provider: 1 - AWS diff --git a/cookiecutter.json b/cookiecutter.json index 970a53795..3fcab4a78 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -16,9 +16,9 @@ "username_type": ["username", "email"], "timezone": "UTC", "windows": "n", - "use_pycharm": "n", + "editor": ["None", "PyCharm", "VS Code"], "use_docker": "n", - "postgresql_version": ["14", "13", "12", "11", "10"], + "postgresql_version": ["15", "14", "13", "12", "11", "10"], "cloud_provider": ["AWS", "GCP", "Azure", "None"], "mail_service": [ "Mailgun", diff --git a/docs/project-generation-options.rst b/docs/project-generation-options.rst index a1d788173..edf2306d4 100644 --- a/docs/project-generation-options.rst +++ b/docs/project-generation-options.rst @@ -53,20 +53,25 @@ timezone: windows: Indicates whether the project should be configured for development on Windows. -use_pycharm: - Indicates whether the project should be configured for development with PyCharm_. +editor: + Select an editor to use. The choices are: + + 1. None + 2. PyCharm_ + 3. `VS Code`_ 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: Select a PostgreSQL_ version to use. The choices are: - 1. 14 - 2. 13 - 3. 12 - 4. 11 - 5. 10 + 1. 15 + 2. 14 + 3. 13 + 4. 12 + 5. 11 + 6. 10 cloud_provider: 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 .. _PyCharm: https://www.jetbrains.com/pycharm/ +.. _VS Code: https://github.com/microsoft/vscode .. _Docker: https://github.com/docker/docker .. _Docker Compose: https://docs.docker.com/compose/ +.. _devcontainer: https://containers.dev/ .. _PostgreSQL: https://www.postgresql.org/docs/ diff --git a/docs/requirements.txt b/docs/requirements.txt index cb8bc03d3..92cbea30f 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,3 @@ sphinx==7.0.1 -sphinx-rtd-theme==1.2.1 -myst-parser==1.0.0 +sphinx-rtd-theme==1.2.2 +myst-parser==2.0.0 diff --git a/docs/settings.rst b/docs/settings.rst index 6dacb7404..0880bce95 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -81,3 +81,6 @@ Other Environment Settings 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) + +DJANGO_ADMIN_FORCE_ALLAUTH (=False) + Force the `admin` sign in process to go through the `django-allauth` workflow. diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index b79985a82..292609403 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -74,12 +74,13 @@ def remove_pycharm_files(): def remove_docker_files(): + shutil.rmtree(".devcontainer") shutil.rmtree("compose") file_names = ["local.yml", "production.yml", ".dockerignore"] for file_name in file_names: 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"] for file_name in file_names: 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 continue os.remove(file_name) - remove_heroku_build_hooks() - - -def remove_heroku_build_hooks(): shutil.rmtree("bin") @@ -194,7 +191,9 @@ def handle_js_runner(choice, use_docker, use_async): "gulp-uglify-es", ] 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( { "dev": "concurrently npm:dev:*", @@ -429,7 +428,7 @@ def main(): if "{{ cookiecutter.username_type }}" == "username": remove_custom_user_manager_files() - if "{{ cookiecutter.use_pycharm }}".lower() == "n": + if "{{ cookiecutter.editor }}".lower() != "PyCharm": remove_pycharm_files() if "{{ cookiecutter.use_docker }}".lower() == "y": @@ -442,15 +441,13 @@ def main(): if "{{ cookiecutter.use_heroku }}".lower() == "n": 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.keep_local_envs_in_vcs }}".lower() == "y": print( INFO + ".env(s) are only utilized when Docker Compose and/or " - "Heroku support is enabled so keeping them does not " - "make sense given your current setup." + TERMINATOR + "Heroku support is enabled so keeping them does not make sense " + "given your current setup." + TERMINATOR ) remove_envs_and_associated_files() else: diff --git a/pyproject.toml b/pyproject.toml index 2b4b98783..2a9f00b29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,3 +27,24 @@ known_first_party = [ "scripts", "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 diff --git a/requirements.txt b/requirements.txt index c06987a2e..d6d0ca754 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,13 +7,14 @@ binaryornot==0.4.4 black==23.3.0 isort==5.12.0 flake8==6.0.0 -django-upgrade==1.13.0 -pre-commit==3.3.2 +django-upgrade==1.14.0 +djlint==1.31.1 +pre-commit==3.3.3 # Testing # ------------------------------------------------------------------------------ -tox==4.5.1 -pytest==7.3.1 +tox==4.6.3 +pytest==7.4.0 pytest-xdist==3.3.1 pytest-cookies==0.7.0 pytest-instafail==0.5.0 @@ -21,7 +22,7 @@ pyyaml==6.0 # Scripting # ------------------------------------------------------------------------------ -PyGithub==1.58.2 +PyGithub==1.59.0 gitpython==3.1.31 jinja2==3.1.2 requests==2.31.0 diff --git a/setup.py b/setup.py index 6adcd3657..03b978f5b 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ except ImportError: from distutils.core import setup # We use calendar versioning -version = "2023.05.18" +version = "2023.07.03" with open("README.rst") as readme_file: long_description = readme_file.read() @@ -24,7 +24,7 @@ setup( classifiers=[ "Development Status :: 4 - Beta", "Environment :: Console", - "Framework :: Django :: 4.1", + "Framework :: Django :: 4.2", "Intended Audience :: Developers", "Natural Language :: English", "License :: OSI Approved :: BSD License", diff --git a/tests/test_cookiecutter_generation.py b/tests/test_cookiecutter_generation.py index 778e3411f..2eb7ae52e 100755 --- a/tests/test_cookiecutter_generation.py +++ b/tests/test_cookiecutter_generation.py @@ -52,10 +52,12 @@ SUPPORTED_COMBINATIONS = [ {"open_source_license": "Not open source"}, {"windows": "y"}, {"windows": "n"}, - {"use_pycharm": "y"}, - {"use_pycharm": "n"}, + {"editor": "None"}, + {"editor": "PyCharm"}, + {"editor": "VS Code"}, {"use_docker": "y"}, {"use_docker": "n"}, + {"postgresql_version": "15"}, {"postgresql_version": "14"}, {"postgresql_version": "13"}, {"postgresql_version": "12"}, @@ -231,7 +233,7 @@ def test_django_upgrade_passes(cookies, context_override): try: sh.django_upgrade( "--target-version", - "4.1", + "4.2", *python_files, _cwd=str(result.project_path), ) @@ -239,6 +241,32 @@ def test_django_upgrade_passes(cookies, context_override): 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( ["use_docker", "expected_test_script"], [ @@ -347,14 +375,15 @@ def test_error_if_incompatible(cookies, context, invalid_context): @pytest.mark.parametrize( - ["use_pycharm", "pycharm_docs_exist"], + ["editor", "pycharm_docs_exist"], [ - ("n", False), - ("y", True), + ("None", False), + ("PyCharm", True), + ("VS Code", False), ], ) -def test_pycharm_docs_removed(cookies, context, use_pycharm, pycharm_docs_exist): - context.update({"use_pycharm": use_pycharm}) +def test_pycharm_docs_removed(cookies, context, editor, pycharm_docs_exist): + context.update({"editor": editor}) result = cookies.bake(extra_context=context) with open(f"{result.project_path}/docs/index.rst") as f: diff --git a/{{cookiecutter.project_slug}}/.devcontainer/bash_history b/{{cookiecutter.project_slug}}/.devcontainer/bash_history new file mode 100644 index 000000000..e69de29bb diff --git a/{{cookiecutter.project_slug}}/.devcontainer/bashrc.override.sh b/{{cookiecutter.project_slug}}/.devcontainer/bashrc.override.sh new file mode 100644 index 000000000..bedddf64b --- /dev/null +++ b/{{cookiecutter.project_slug}}/.devcontainer/bashrc.override.sh @@ -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)" diff --git a/{{cookiecutter.project_slug}}/.devcontainer/devcontainer.json b/{{cookiecutter.project_slug}}/.devcontainer/devcontainer.json new file mode 100644 index 000000000..c11b8dd9a --- /dev/null +++ b/{{cookiecutter.project_slug}}/.devcontainer/devcontainer.json @@ -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 container’s 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" +} diff --git a/{{cookiecutter.project_slug}}/.github/workflows/ci.yml b/{{cookiecutter.project_slug}}/.github/workflows/ci.yml index ac231ee72..8f9824e8f 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/ci.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/ci.yml @@ -49,7 +49,7 @@ jobs: - 6379:6379 {%- endif %} postgres: - image: postgres:12 + image: postgres:{{ cookiecutter.postgresql_version }} ports: - 5432:5432 env: diff --git a/{{cookiecutter.project_slug}}/.gitignore b/{{cookiecutter.project_slug}}/.gitignore index 19bb2bc07..541f40846 100644 --- a/{{cookiecutter.project_slug}}/.gitignore +++ b/{{cookiecutter.project_slug}}/.gitignore @@ -161,11 +161,10 @@ typings/ !.vscode/extensions.json *.code-workspace -# Local History for Visual Studio Code -.history/ +# Local History for devcontainer +.devcontainer/bash_history - -{% if cookiecutter.use_pycharm == 'y' -%} +{% if cookiecutter.editor == 'PyCharm' -%} # Provided default Pycharm Run/Debug Configurations should be tracked by git # In case of local modifications made by Pycharm, use update-index command # for each changed file, like this: diff --git a/{{cookiecutter.project_slug}}/.idea/runConfigurations/runserver_plus.xml b/{{cookiecutter.project_slug}}/.idea/runConfigurations/runserver_plus.xml new file mode 100644 index 000000000..242f861a6 --- /dev/null +++ b/{{cookiecutter.project_slug}}/.idea/runConfigurations/runserver_plus.xml @@ -0,0 +1,33 @@ + + + + + diff --git a/{{cookiecutter.project_slug}}/.pre-commit-config.yaml b/{{cookiecutter.project_slug}}/.pre-commit-config.yaml index 3a0411d81..0d1265ac2 100644 --- a/{{cookiecutter.project_slug}}/.pre-commit-config.yaml +++ b/{{cookiecutter.project_slug}}/.pre-commit-config.yaml @@ -16,6 +16,7 @@ repos: - id: check-case-conflict - id: check-docstring-first - id: detect-private-key +{%- if cookiecutter.frontend_pipeline in ["Webpack", "Gulp"] %} - repo: https://github.com/pre-commit/mirrors-prettier rev: v3.0.0-alpha.9-for-vscode @@ -23,15 +24,16 @@ repos: - id: prettier args: ['--tab-width', '2', '--single-quote'] exclude: '{{cookiecutter.project_slug}}/templates/' +{%- endif %} - repo: https://github.com/adamchainz/django-upgrade - rev: '1.13.0' + rev: '1.14.0' hooks: - id: django-upgrade - args: ['--target-version', '4.1'] + args: ['--target-version', '4.2'] - repo: https://github.com/asottile/pyupgrade - rev: v3.4.0 + rev: v3.7.0 hooks: - id: pyupgrade args: [--py311-plus] @@ -51,6 +53,12 @@ repos: hooks: - 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 ci: autoupdate_schedule: weekly diff --git a/{{cookiecutter.project_slug}}/bin/post_compile b/{{cookiecutter.project_slug}}/bin/post_compile index a9c94b39a..16719f493 100644 --- a/{{cookiecutter.project_slug}}/bin/post_compile +++ b/{{cookiecutter.project_slug}}/bin/post_compile @@ -1,4 +1,5 @@ #!/usr/bin/env bash +{%- if cookiecutter.frontend_pipeline == "Django Compressor" %} compress_enabled() { python << END @@ -19,4 +20,7 @@ if compress_enabled then python manage.py compress fi +{%- endif %} + python manage.py collectstatic --noinput +python manage.py compilemessages -i site-packages diff --git a/{{cookiecutter.project_slug}}/compose/local/django/Dockerfile b/{{cookiecutter.project_slug}}/compose/local/django/Dockerfile index db48870d8..3636ce1ef 100644 --- a/{{cookiecutter.project_slug}}/compose/local/django/Dockerfile +++ b/{{cookiecutter.project_slug}}/compose/local/django/Dockerfile @@ -1,5 +1,5 @@ # 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 FROM python as python-build-stage @@ -33,6 +33,18 @@ ENV BUILD_ENV ${BUILD_ENVIRONMENT} 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 RUN apt-get update && apt-get install --no-install-recommends -y \ # psycopg2 dependencies @@ -49,7 +61,7 @@ COPY --from=python-build-stage /usr/src/app/wheels /wheels/ # use wheels to install python dependencies RUN pip install --no-cache-dir --no-index --find-links=/wheels/ /wheels/* \ - && rm -rf /wheels/ + && rm -rf /wheels/ COPY ./compose/production/django/entrypoint /entrypoint RUN sed -i 's/\r$//g' /entrypoint diff --git a/{{cookiecutter.project_slug}}/compose/local/django/celery/beat/start b/{{cookiecutter.project_slug}}/compose/local/django/celery/beat/start index 61f83968b..8adc4891a 100644 --- a/{{cookiecutter.project_slug}}/compose/local/django/celery/beat/start +++ b/{{cookiecutter.project_slug}}/compose/local/django/celery/beat/start @@ -5,4 +5,4 @@ set -o nounset 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' diff --git a/{{cookiecutter.project_slug}}/compose/local/django/celery/flower/start b/{{cookiecutter.project_slug}}/compose/local/django/celery/flower/start index ac3cc6b36..b4783d2f0 100644 --- a/{{cookiecutter.project_slug}}/compose/local/django/celery/flower/start +++ b/{{cookiecutter.project_slug}}/compose/local/django/celery/flower/start @@ -3,6 +3,6 @@ set -o errexit set -o nounset -exec watchfiles celery.__main__.main \ +exec watchfiles --filter python celery.__main__.main \ --args \ "-A config.celery_app -b \"${CELERY_BROKER_URL}\" flower --basic_auth=\"${CELERY_FLOWER_USER}:${CELERY_FLOWER_PASSWORD}\"" diff --git a/{{cookiecutter.project_slug}}/compose/local/django/celery/worker/start b/{{cookiecutter.project_slug}}/compose/local/django/celery/worker/start index 16341fdd1..183a80159 100644 --- a/{{cookiecutter.project_slug}}/compose/local/django/celery/worker/start +++ b/{{cookiecutter.project_slug}}/compose/local/django/celery/worker/start @@ -4,4 +4,4 @@ set -o errexit 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' diff --git a/{{cookiecutter.project_slug}}/compose/local/django/start b/{{cookiecutter.project_slug}}/compose/local/django/start index 6415d7fb4..ec57dc8e4 100644 --- a/{{cookiecutter.project_slug}}/compose/local/django/start +++ b/{{cookiecutter.project_slug}}/compose/local/django/start @@ -9,5 +9,5 @@ python manage.py migrate {%- if cookiecutter.use_async == 'y' %} exec uvicorn config.asgi:application --host 0.0.0.0 --reload --reload-include '*.html' {%- else %} -exec python manage.py runserver 0.0.0.0:8000 +exec python manage.py runserver_plus 0.0.0.0:8000 {%- endif %} diff --git a/{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile b/{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile index 8239a6635..f9895a083 100644 --- a/{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile +++ b/{{cookiecutter.project_slug}}/compose/local/docs/Dockerfile @@ -1,5 +1,5 @@ # 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 diff --git a/{{cookiecutter.project_slug}}/compose/production/django/Dockerfile b/{{cookiecutter.project_slug}}/compose/production/django/Dockerfile index 4c8695a57..a48cbc4af 100644 --- a/{{cookiecutter.project_slug}}/compose/production/django/Dockerfile +++ b/{{cookiecutter.project_slug}}/compose/production/django/Dockerfile @@ -25,7 +25,7 @@ RUN npm run build {%- endif %} # define an alias for the specific python version used in this file. -FROM python:3.11.3-slim-bullseye as python +FROM python:3.11.4-slim-bullseye as python # Python build stage FROM python as python-build-stage @@ -121,4 +121,11 @@ RUN chown django:django ${APP_HOME} 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"] diff --git a/{{cookiecutter.project_slug}}/compose/production/django/entrypoint b/{{cookiecutter.project_slug}}/compose/production/django/entrypoint index 2fbcad955..dd07f2d2a 100644 --- a/{{cookiecutter.project_slug}}/compose/production/django/entrypoint +++ b/{{cookiecutter.project_slug}}/compose/production/django/entrypoint @@ -20,14 +20,14 @@ python << END import sys import time -import psycopg2 +import psycopg suggest_unrecoverable_after = 30 start = time.time() while True: try: - psycopg2.connect( + psycopg.connect( dbname="${POSTGRES_DB}", user="${POSTGRES_USER}", password="${POSTGRES_PASSWORD}", @@ -35,7 +35,7 @@ while True: port="${POSTGRES_PORT}", ) break - except psycopg2.OperationalError as error: + except psycopg.OperationalError as error: sys.stderr.write("Waiting for PostgreSQL to become available...\n") if time.time() - start > suggest_unrecoverable_after: diff --git a/{{cookiecutter.project_slug}}/compose/production/traefik/Dockerfile b/{{cookiecutter.project_slug}}/compose/production/traefik/Dockerfile index 581bbfebd..bdedff720 100644 --- a/{{cookiecutter.project_slug}}/compose/production/traefik/Dockerfile +++ b/{{cookiecutter.project_slug}}/compose/production/traefik/Dockerfile @@ -1,4 +1,4 @@ -FROM traefik:2.10.1 +FROM traefik:2.10.3 RUN mkdir -p /etc/traefik/acme \ && touch /etc/traefik/acme/acme.json \ && chmod 600 /etc/traefik/acme/acme.json diff --git a/{{cookiecutter.project_slug}}/config/settings/base.py b/{{cookiecutter.project_slug}}/config/settings/base.py index c0ca31f36..c9feedea1 100644 --- a/{{cookiecutter.project_slug}}/config/settings/base.py +++ b/{{cookiecutter.project_slug}}/config/settings/base.py @@ -26,6 +26,12 @@ DEBUG = env.bool("DJANGO_DEBUG", False) TIME_ZONE = "{{ cookiecutter.timezone }}" # https://docs.djangoproject.com/en/dev/ref/settings/#language-code 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 SITE_ID = 1 # https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n @@ -244,6 +250,9 @@ ADMIN_URL = "admin/" ADMINS = [("""{{cookiecutter.author_name}}""", "{{cookiecutter.email}}")] # https://docs.djangoproject.com/en/dev/ref/settings/#managers 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 # ------------------------------------------------------------------------------ diff --git a/{{cookiecutter.project_slug}}/docs/index.rst b/{{cookiecutter.project_slug}}/docs/index.rst index cb4cbaeda..10b1c936f 100644 --- a/{{cookiecutter.project_slug}}/docs/index.rst +++ b/{{cookiecutter.project_slug}}/docs/index.rst @@ -10,7 +10,7 @@ Welcome to {{ cookiecutter.project_name }}'s documentation! :maxdepth: 2 :caption: Contents: - howto{% if cookiecutter.use_pycharm == 'y' %} + howto{% if cookiecutter.editor == 'PyCharm' %} pycharm/configuration{% endif %} users diff --git a/{{cookiecutter.project_slug}}/locale/README.md b/{{cookiecutter.project_slug}}/locale/README.md new file mode 100644 index 000000000..b2a8a0ef2 --- /dev/null +++ b/{{cookiecutter.project_slug}}/locale/README.md @@ -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 `/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. diff --git a/{{cookiecutter.project_slug}}/locale/README.rst b/{{cookiecutter.project_slug}}/locale/README.rst deleted file mode 100644 index c2f1dcd6f..000000000 --- a/{{cookiecutter.project_slug}}/locale/README.rst +++ /dev/null @@ -1,6 +0,0 @@ -Translations -============ - -Translations will be placed in this folder when running:: - - python manage.py makemessages diff --git a/{{cookiecutter.project_slug}}/locale/en_US/LC_MESSAGES/django.po b/{{cookiecutter.project_slug}}/locale/en_US/LC_MESSAGES/django.po new file mode 100644 index 000000000..6a4aa2e0b --- /dev/null +++ b/{{cookiecutter.project_slug}}/locale/en_US/LC_MESSAGES/django.po @@ -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" diff --git a/{{cookiecutter.project_slug}}/locale/pt_BR/LC_MESSAGES/django.po b/{{cookiecutter.project_slug}}/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 000000000..2556abba8 --- /dev/null +++ b/{{cookiecutter.project_slug}}/locale/pt_BR/LC_MESSAGES/django.po @@ -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 %(email)s is an e-mail " +"address for user %(user_display)s." +msgstr "" +"Confirme se %(email)s é 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 issue a new e-mail confirmation request." +msgstr "Este link de confirmação de e-mail expirou ou é inválido. " +"Por favor, emita um novo pedido de confirmação por e-mail." + +#: {{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, sign up for a %(site_name)s account and " +"sign in below:" +msgstr "Ou, cadastre-se 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 sign up first." +msgstr "Se você ainda não criou uma conta, registre-se primeiro." + +#: {{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 new password reset." +msgstr "O link de redefinição de senha era inválido, possivelmente porque já foi usado. " +"Solicite uma nova redefinição de senha." + +#: {{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 sign in." +msgstr "já tem uma conta? Então, por favor, faça login." + +#: {{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 "" +"Note: you can still change your e-" +"mail address." +msgstr "Nota: você ainda pode alterar seu endereço de e-mail." + +#: {{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" diff --git a/{{cookiecutter.project_slug}}/package.json b/{{cookiecutter.project_slug}}/package.json index fdfd26bf3..99b984da6 100644 --- a/{{cookiecutter.project_slug}}/package.json +++ b/{{cookiecutter.project_slug}}/package.json @@ -25,7 +25,7 @@ "pixrem": "^5.0.0", "postcss": "^8.3.11", "postcss-loader": "^7.0.2", - "postcss-preset-env": "^8.0.1", + "postcss-preset-env": "^9.0.0", "sass": "^1.43.4", "sass-loader": "^13.2.0", "webpack": "^5.65.0", diff --git a/{{cookiecutter.project_slug}}/pyproject.toml b/{{cookiecutter.project_slug}}/pyproject.toml index 6acac9b2c..7e4c9aa9c 100644 --- a/{{cookiecutter.project_slug}}/pyproject.toml +++ b/{{cookiecutter.project_slug}}/pyproject.toml @@ -90,3 +90,23 @@ generated-members = [ "save", "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 diff --git a/{{cookiecutter.project_slug}}/requirements/base.txt b/{{cookiecutter.project_slug}}/requirements/base.txt index ee00cda7b..47a0bc34b 100644 --- a/{{cookiecutter.project_slug}}/requirements/base.txt +++ b/{{cookiecutter.project_slug}}/requirements/base.txt @@ -9,17 +9,17 @@ rcssmin==1.1.1 # https://github.com/ndparker/rcssmin {%- endif %} argon2-cffi==21.3.0 # https://github.com/hynek/argon2_cffi {%- if cookiecutter.use_whitenoise == 'y' %} -whitenoise==6.4.0 # https://github.com/evansd/whitenoise +whitenoise==6.5.0 # https://github.com/evansd/whitenoise {%- 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" %} -hiredis==2.2.2 # https://github.com/redis/hiredis-py +hiredis==2.2.3 # https://github.com/redis/hiredis-py {%- endif %} {%- 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 {%- 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 %} {%- if cookiecutter.use_async == 'y' %} @@ -28,23 +28,23 @@ uvicorn[standard]==0.22.0 # https://github.com/encode/uvicorn # 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-model-utils==4.3.1 # https://github.com/jazzband/django-model-utils 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 crispy-bootstrap5==0.7 # https://github.com/django-crispy-forms/crispy-bootstrap5 {%- 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 %} -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' %} # 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==0.26.2 # https://github.com/tfranzel/drf-spectacular +drf-spectacular==0.26.3 # https://github.com/tfranzel/drf-spectacular {%- endif %} {%- 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 %} diff --git a/{{cookiecutter.project_slug}}/requirements/local.txt b/{{cookiecutter.project_slug}}/requirements/local.txt index 9fd6ddba9..90739c7eb 100644 --- a/{{cookiecutter.project_slug}}/requirements/local.txt +++ b/{{cookiecutter.project_slug}}/requirements/local.txt @@ -1,11 +1,11 @@ -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 {%- 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 %} -psycopg2-binary==2.9.6 # https://github.com/psycopg/psycopg2 +psycopg[binary]==3.1.9 # https://github.com/psycopg/psycopg {%- endif %} {%- if cookiecutter.use_async == 'y' or cookiecutter.use_celery == 'y' %} watchfiles==0.19.0 # https://github.com/samuelcolvin/watchfiles @@ -13,12 +13,12 @@ watchfiles==0.19.0 # https://github.com/samuelcolvin/watchfiles # Testing # ------------------------------------------------------------------------------ -mypy==1.2.0 # https://github.com/python/mypy -django-stubs==4.2.0 # https://github.com/typeddjango/django-stubs -pytest==7.3.1 # https://github.com/pytest-dev/pytest +mypy==1.4.1 # https://github.com/python/mypy +django-stubs==4.2.3 # https://github.com/typeddjango/django-stubs +pytest==7.4.0 # https://github.com/pytest-dev/pytest pytest-sugar==0.9.7 # https://github.com/Frozenball/pytest-sugar {%- 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 %} # 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-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 +djlint==1.31.1 # https://github.com/Riverside-Healthcare/djLint pylint-django==2.5.3 # https://github.com/PyCQA/pylint-django {%- if cookiecutter.use_celery == 'y' %} pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery {%- endif %} -pre-commit==3.3.2 # https://github.com/pre-commit/pre-commit +pre-commit==3.3.3 # https://github.com/pre-commit/pre-commit # Django # ------------------------------------------------------------------------------ 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-extensions==3.2.1 # https://github.com/django-extensions/django-extensions +django-debug-toolbar==4.1.0 # https://github.com/jazzband/django-debug-toolbar +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 pytest-django==4.5.2 # https://github.com/pytest-dev/pytest-django diff --git a/{{cookiecutter.project_slug}}/requirements/production.txt b/{{cookiecutter.project_slug}}/requirements/production.txt index 663619693..eb6a14c28 100644 --- a/{{cookiecutter.project_slug}}/requirements/production.txt +++ b/{{cookiecutter.project_slug}}/requirements/production.txt @@ -3,15 +3,15 @@ -r base.txt 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' %} Collectfast==2.2.0 # https://github.com/antonagestam/collectfast {%- endif %} {%- 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 %} {%- 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 %} # 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 {%- endif %} {%- 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' %} -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' %} -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' %} -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' %} -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' %} -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' %} -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' %} -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' %} -django-anymail==9.2 # https://github.com/anymail/django-anymail +django-anymail==10.0 # https://github.com/anymail/django-anymail {%- endif %} diff --git a/{{cookiecutter.project_slug}}/runtime.txt b/{{cookiecutter.project_slug}}/runtime.txt index afe12ad1b..431fc7e8c 100644 --- a/{{cookiecutter.project_slug}}/runtime.txt +++ b/{{cookiecutter.project_slug}}/runtime.txt @@ -1 +1 @@ -python-3.11.3 +python-3.11.4 diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/403.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/403.html index 4c4745f7d..d90b33f9b 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/403.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/403.html @@ -1,10 +1,14 @@ {% raw %}{% extends "base.html" %} -{% block title %}Forbidden (403){% endblock %} - +{% block title %}Forbidden (403){% endblock title %} {% block content %} -

Forbidden (403)

- -

{% if exception %}{{ exception }}{% else %}You're not allowed to access this page.{% endif %}

+

Forbidden (403)

+

+ {% if exception %} + {{ exception }} + {% else %} + You're not allowed to access this page. + {% endif %} +

{% endblock content %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/404.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/404.html index d98241858..621596412 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/404.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/404.html @@ -1,10 +1,14 @@ {% raw %}{% extends "base.html" %} -{% block title %}Page not found{% endblock %} - +{% block title %}Page not found{% endblock title %} {% block content %} -

Page not found

- -

{% if exception %}{{ exception }}{% else %}This is not the page you were looking for.{% endif %}

+

Page not found

+

+ {% if exception %} + {{ exception }} + {% else %} + This is not the page you were looking for. + {% endif %} +

{% endblock content %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/500.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/500.html index 481bb2d0b..890320164 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/500.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/500.html @@ -1,12 +1,11 @@ {% raw %}{% extends "base.html" %} -{% block title %}Server Error{% endblock %} - +{% block title %}Server Error{% endblock title %} {% block content %} -

Ooops!!! 500

- -

Looks like something went wrong!

- -

We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing.

+

Ooops!!! 500

+

Looks like something went wrong!

+

+ We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing. +

{% endblock content %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/account_inactive.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/account_inactive.html index ab910820e..a9112cf09 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/account_inactive.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/account_inactive.html @@ -2,11 +2,11 @@ {% load i18n %} -{% block head_title %}{% translate "Account Inactive" %}{% endblock %} - +{% block head_title %} + {% translate "Account Inactive" %} +{% endblock head_title %} {% block inner %} -

{% translate "Account Inactive" %}

- -

{% translate "This account is inactive." %}

-{% endblock %} +

{% translate "Account Inactive" %}

+

{% translate "This account is inactive." %}

+{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/base.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/base.html index 03c86724b..057618257 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/base.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/base.html @@ -1,11 +1,14 @@ {% 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 inner %}{% endblock %} +
+
+ {% block inner %}{% endblock inner %} +
-
-{% endblock %} +{% endblock content %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/email.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/email.html index 1faa2b9fd..37770f00c 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/email.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/email.html @@ -4,76 +4,77 @@ {% load i18n %} {% load crispy_forms_tags %} -{% block head_title %}{% translate "Account" %}{% endblock %} - +{% block head_title %} + {% translate "Account" %} +{% endblock head_title %} {% block inner %} -

{% translate "E-mail Addresses" %}

- -{% if user.emailaddress_set.all %} -

{% translate 'The following e-mail addresses are associated with your account:' %}

- - - -{% else %} -

{% translate 'Warning:'%} {% 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." %}

- -{% endif %} - - -

{% translate "Add E-mail Address" %}

- -
- {% csrf_token %} - {{ form|crispy }} - +

{% translate "E-mail Addresses" %}

+ {% if user.emailaddress_set.all %} +

{% translate "The following e-mail addresses are associated with your account:" %}

+ + {% csrf_token %} +
+ {% for emailaddress in user.emailaddress_set.all %} +
+ +
+ {% endfor %} +
+ + + +
+
- -{% endblock %} - - + {% else %} +

+ {% translate "Warning:" %} {% 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." %} +

+ {% endif %} +

{% translate "Add E-mail Address" %}

+
+ {% csrf_token %} + {{ form|crispy }} + +
+{% endblock inner %} {% block inline_javascript %} -{{ block.super }} - -{% endblock %} + +{% endblock inline_javascript %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/email_confirm.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/email_confirm.html index 5e4924c83..40ca4a47b 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/email_confirm.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/email_confirm.html @@ -3,30 +3,26 @@ {% load i18n %} {% load account %} -{% block head_title %}{% translate "Confirm E-mail Address" %}{% endblock %} - - +{% block head_title %} + {% translate "Confirm E-mail Address" %} +{% endblock head_title %} {% block inner %} -

{% translate "Confirm E-mail Address" %}

- -{% if confirmation %} - -{% user_display confirmation.email_address.user as user_display %} - -

{% blocktranslate with confirmation.email_address.email as email %}Please confirm that {{ email }} is an e-mail address for user {{ user_display }}.{% endblocktranslate %}

- -
-{% csrf_token %} - -
- -{% else %} - -{% url 'account_email' as email_url %} - -

{% blocktranslate %}This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request.{% endblocktranslate %}

- -{% endif %} - -{% endblock %} +

{% translate "Confirm E-mail Address" %}

+ {% if confirmation %} + {% user_display confirmation.email_address.user as user_display %} +

+ {% blocktranslate with confirmation.email_address.email as email %}Please confirm that {{ email }} is an e-mail address for user {{ user_display }}.{% endblocktranslate %} +

+
+ {% csrf_token %} + +
+ {% else %} + {% url 'account_email' as email_url %} +

+ {% blocktranslate %}This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request.{% endblocktranslate %} +

+ {% endif %} +{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/login.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/login.html index 25a292eda..5737afc06 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/login.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/login.html @@ -4,57 +4,50 @@ {% load account socialaccount %} {% load crispy_forms_tags %} -{% block head_title %}{% translate "Sign In" %}{% endblock %} - +{% block head_title %} + {% translate "Sign In" %} +{% endblock head_title %} {% block inner %} - -

{% translate "Sign In" %}

- -{% get_providers as socialaccount_providers %} - -{% if socialaccount_providers %} -

- {% translate "Please sign in with one of your existing third party accounts:" %} - {% if ACCOUNT_ALLOW_REGISTRATION %} - {% blocktranslate trimmed %} - Or, sign up - for a {{ site_name }} account and sign in below: - {% endblocktranslate %} - {% endif %} -

- -
- -
    - {% include "socialaccount/snippets/provider_list.html" with process="login" %} -
- - - -
- - {% include "socialaccount/snippets/login_extra.html" %} - -{% else %} - {% if ACCOUNT_ALLOW_REGISTRATION %} +

{% translate "Sign In" %}

+ {% get_providers as socialaccount_providers %} + {% if socialaccount_providers %}

- {% blocktranslate trimmed %} - If you have not created an account yet, then please - sign up first. - {% endblocktranslate %} + {% translate "Please sign in with one of your existing third party accounts:" %} + {% if ACCOUNT_ALLOW_REGISTRATION %} + {% blocktranslate trimmed %} + Or, sign up + for a {{ site_name }} account and sign in below: + {% endblocktranslate %} + {% endif %}

+
+
    + {% include "socialaccount/snippets/provider_list.html" with process="login" %} +
+ +
+ {% include "socialaccount/snippets/login_extra.html" %} + {% else %} + {% if ACCOUNT_ALLOW_REGISTRATION %} +

+ {% blocktranslate trimmed %} + If you have not created an account yet, then please + sign up first. + {% endblocktranslate %} +

+ {% endif %} {% endif %} -{% endif %} - - - -{% endblock %} + +{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/logout.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/logout.html index 5edc60478..43ae9ed38 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/logout.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/logout.html @@ -2,19 +2,20 @@ {% load i18n %} -{% block head_title %}{% translate "Sign Out" %}{% endblock %} - +{% block head_title %} + {% translate "Sign Out" %} +{% endblock head_title %} {% block inner %} -

{% translate "Sign Out" %}

- -

{% translate 'Are you sure you want to sign out?' %}

- -
- {% csrf_token %} - {% if redirect_field_value %} - - {% endif %} - -
-{% endblock %} +

{% translate "Sign Out" %}

+

{% translate "Are you sure you want to sign out?" %}

+
+ {% csrf_token %} + {% if redirect_field_value %} + + {% endif %} + +
+{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_change.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_change.html index b8dd7ac53..2e6110d5d 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_change.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_change.html @@ -3,15 +3,17 @@ {% load i18n %} {% load crispy_forms_tags %} -{% block head_title %}{% translate "Change Password" %}{% endblock %} - +{% block head_title %} + {% translate "Change Password" %} +{% endblock head_title %} {% block inner %} -

{% translate "Change Password" %}

- -
- {% csrf_token %} - {{ form|crispy }} - -
-{% endblock %} +

{% translate "Change Password" %}

+
+ {% csrf_token %} + {{ form|crispy }} + +
+{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset.html index f424b2111..0c184269a 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset.html @@ -4,23 +4,26 @@ {% load account %} {% load crispy_forms_tags %} -{% block head_title %}{% translate "Password Reset" %}{% endblock %} - +{% block head_title %} + {% translate "Password Reset" %} +{% endblock head_title %} {% block inner %} - -

{% translate "Password Reset" %}

- {% if user.is_authenticated %} +

{% translate "Password Reset" %}

+ {% if user.is_authenticated %} {% include "account/snippets/already_logged_in.html" %} - {% endif %} - -

{% translate "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}

- -
- {% csrf_token %} - {{ form|crispy }} - -
- -

{% blocktranslate %}Please contact us if you have any trouble resetting your password.{% endblocktranslate %}

-{% endblock %} + {% endif %} +

+ {% translate "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %} +

+
+ {% csrf_token %} + {{ form|crispy }} + +
+

{% blocktranslate %}Please contact us if you have any trouble resetting your password.{% endblocktranslate %}

+{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset_done.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset_done.html index 76d07eb21..a596425bb 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset_done.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset_done.html @@ -3,15 +3,16 @@ {% load i18n %} {% load account %} -{% block head_title %}{% translate "Password Reset" %}{% endblock %} - +{% block head_title %} + {% translate "Password Reset" %} +{% endblock head_title %} {% block inner %} -

{% translate "Password Reset" %}

- - {% if user.is_authenticated %} +

{% translate "Password Reset" %}

+ {% if user.is_authenticated %} {% include "account/snippets/already_logged_in.html" %} - {% endif %} - -

{% blocktranslate %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}

-{% endblock %} + {% endif %} +

+ {% blocktranslate %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %} +

+{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html index ce5d72a6d..a958ba089 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html @@ -2,24 +2,36 @@ {% load i18n %} {% load crispy_forms_tags %} -{% block head_title %}{% translate "Change Password" %}{% endblock %} +{% block head_title %} + {% translate "Change Password" %} +{% endblock head_title %} {% block inner %} -

{% if token_fail %}{% translate "Bad Token" %}{% else %}{% translate "Change Password" %}{% endif %}

- +

{% if token_fail %} - {% url 'account_reset_password' as passwd_reset_url %} -

{% blocktranslate %}The password reset link was invalid, possibly because it has already been used. Please request a new password reset.{% endblocktranslate %}

+ {% translate "Bad Token" %} {% else %} - {% if form %} -
- {% csrf_token %} - {{ form|crispy }} - -
- {% else %} -

{% translate 'Your password is now changed.' %}

- {% endif %} + {% translate "Change Password" %} {% endif %} -{% endblock %} +

+ {% if token_fail %} + {% url 'account_reset_password' as passwd_reset_url %} +

+ {% blocktranslate %}The password reset link was invalid, possibly because it has already been used. Please request a new password reset.{% endblocktranslate %} +

+ {% else %} + {% if form %} +
+ {% csrf_token %} + {{ form|crispy }} + +
+ {% else %} +

{% translate "Your password is now changed." %}

+ {% endif %} + {% endif %} +{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html index 34123fd53..ee399b404 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html @@ -1,10 +1,12 @@ {% raw %}{% extends "account/base.html" %} {% load i18n %} -{% block head_title %}{% translate "Change Password" %}{% endblock %} +{% block head_title %} + {% translate "Change Password" %} +{% endblock head_title %} {% block inner %} -

{% translate "Change Password" %}

-

{% translate 'Your password is now changed.' %}

-{% endblock %} +

{% translate "Change Password" %}

+

{% translate "Your password is now changed." %}

+{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_set.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_set.html index 812410fc0..3efc30874 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_set.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/password_set.html @@ -3,15 +3,20 @@ {% load i18n %} {% load crispy_forms_tags %} -{% block head_title %}{% translate "Set Password" %}{% endblock %} - +{% block head_title %} + {% translate "Set Password" %} +{% endblock head_title %} {% block inner %} -

{% translate "Set Password" %}

- -
- {% csrf_token %} - {{ form|crispy }} - -
-{% endblock %} +

{% translate "Set Password" %}

+
+ {% csrf_token %} + {{ form|crispy }} + +
+{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/signup.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/signup.html index 8c1c11aca..54150a474 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/signup.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/signup.html @@ -3,21 +3,26 @@ {% load i18n %} {% load crispy_forms_tags %} -{% block head_title %}{% translate "Signup" %}{% endblock %} - +{% block head_title %} + {% translate "Signup" %} +{% endblock head_title %} {% block inner %} -

{% translate "Sign Up" %}

- -

{% blocktranslate %}Already have an account? Then please sign in.{% endblocktranslate %}

- - - -{% endblock %} +

{% translate "Sign Up" %}

+

+ {% blocktranslate %}Already have an account? Then please sign in.{% endblocktranslate %} +

+ +{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/signup_closed.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/signup_closed.html index c2e64d14f..b3472ed6d 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/signup_closed.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/signup_closed.html @@ -2,11 +2,11 @@ {% load i18n %} -{% block head_title %}{% translate "Sign Up Closed" %}{% endblock %} - +{% block head_title %} + {% translate "Sign Up Closed" %} +{% endblock head_title %} {% block inner %} -

{% translate "Sign Up Closed" %}

- -

{% translate "We are sorry, but the sign up is currently closed." %}

-{% endblock %} +

{% translate "Sign Up Closed" %}

+

{% translate "We are sorry, but the sign up is currently closed." %}

+{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/verification_sent.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/verification_sent.html index be8f1cef9..d71bbc41a 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/verification_sent.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/verification_sent.html @@ -2,12 +2,13 @@ {% 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 %} -

{% translate "Verify Your E-mail Address" %}

- -

{% 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 %}

- -{% endblock %} +

{% translate "Verify Your E-mail Address" %}

+

+ {% 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 %} +

+{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/verified_email_required.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/verified_email_required.html index 2148a1804..b736581ce 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/verified_email_required.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/account/verified_email_required.html @@ -2,21 +2,24 @@ {% 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 %} -

{% translate "Verify Your E-mail Address" %}

- -{% url 'account_email' as email_url %} - -

{% blocktranslate %}This part of the site requires us to verify that +

{% translate "Verify Your E-mail Address" %}

+ {% url 'account_email' as email_url %} +

+ {% blocktranslate %}This part of the site requires us to verify that you are who you claim to be. For this purpose, we require that you -verify ownership of your e-mail address. {% endblocktranslate %}

- -

{% blocktranslate %}We have sent an e-mail to you for +verify ownership of your e-mail address. {% endblocktranslate %} +

+

+ {% blocktranslate %}We have sent an e-mail to you for verification. Please click on the link inside this e-mail. Please -contact us if you do not receive it within a few minutes.{% endblocktranslate %}

- -

{% blocktranslate %}Note: you can still change your e-mail address.{% endblocktranslate %}

-{% endblock %} +contact us if you do not receive it within a few minutes.{% endblocktranslate %} +

+

+ {% blocktranslate %}Note: you can still change your e-mail address.{% endblocktranslate %} +

+{% endblock inner %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html index 44f0d5c52..421973e57 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html @@ -1,150 +1,194 @@ -{% raw %}{% load static i18n {% endraw %} -{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}compress -{%- endif %}{% raw %}%}{% endraw %} -{%- if cookiecutter.frontend_pipeline == 'Webpack' %}{% raw %}{% load render_bundle from webpack_loader %}{% endraw %} +{% raw %} +{% load static i18n {% 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 %} {% get_current_language as LANGUAGE_CODE %} - - - {% block title %}{% endraw %}{{ cookiecutter.project_name }}{% raw %}{% endblock title %} - - - - - - - {% block css %} - {%- endraw %} - {%- if cookiecutter.frontend_pipeline in ['None', 'Django Compressor'] %} + + + + {% block title %} + {% endraw %}{{ cookiecutter.project_name }}{% raw %} + {% endblock title %} + + + + + + {% block css %} + {%- endraw %} + {%- if cookiecutter.frontend_pipeline in ['None', 'Django Compressor'] %} {%- raw %} - - {%- endraw %} - {%- endif %} - {%- raw %} - - - - {%- endraw %}{% if cookiecutter.frontend_pipeline == 'None' %}{% raw %} - - {%- endraw %}{% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}{% raw %} - {% compress css %} - - {% endcompress %} - {%- endraw %}{% elif cookiecutter.frontend_pipeline == 'Gulp' %}{% raw %} - - {%- endraw %}{% elif cookiecutter.frontend_pipeline == "Webpack" %}{% raw %} - {% render_bundle 'project' 'css' %} - {%- endraw %}{% endif %}{% raw %} - {% endblock %} - + +{%- endraw %} +{% if cookiecutter.frontend_pipeline == 'None' %} + {% raw %} + +{%- endraw %} +{% elif cookiecutter.frontend_pipeline == 'Django Compressor' %} +{% raw %} +{% compress css %} + +{% endcompress %} +{%- endraw %} +{% elif cookiecutter.frontend_pipeline == 'Gulp' %} +{% raw %} + +{%- endraw %} +{% elif cookiecutter.frontend_pipeline == "Webpack" %} +{% raw %} +{% render_bundle 'project' 'css' %} +{%- endraw %} +{% endif %} +{% raw %} +{% endblock css %} + - {# Placed at the top of the document so pages load faster with defer #} - {% block javascript %} - {%- endraw %}{% if cookiecutter.frontend_pipeline == 'Gulp' %}{% raw %} - - - {%- endraw %}{% elif cookiecutter.frontend_pipeline == "Webpack" %}{% raw %} - - {% render_bundle 'vendors' 'js' attrs='defer' %} - {%- endraw %}{% else %}{% raw %} - - - - {%- endraw %}{% endif %}{% raw %} - - - {%- endraw %}{% if cookiecutter.frontend_pipeline == 'None' %}{% raw %} - - {%- endraw %}{% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}{% raw %} - {% compress js %} - - {% endcompress %} - {%- endraw %}{% elif cookiecutter.frontend_pipeline == 'Gulp' %}{% raw %} - - {%- endraw %}{% elif cookiecutter.frontend_pipeline == "Webpack" %}{% raw %} - {% render_bundle 'project' 'js' attrs='defer' %} - {%- endraw %}{% endif %}{% raw %} - - {% endblock javascript %} - - - - - -
- - -
- -
- - {% if messages %} - {% for message in messages %} -
- {{ message }} - -
- {% endfor %} - {% endif %} - - {% block content %} -

Use this document as a way to quick start any new project.

- {% endblock content %} - -
- - {% block modal %}{% endblock modal %} - - {% block inline_javascript %} +
+ + +
+ {% if messages %} + {% for message in messages %} +
+ {{ message }} + +
+ {% endfor %} + {% endif %} + {% block content %} +

Use this document as a way to quick start any new project.

+ {% endblock content %} +
+ + {% block modal %} + {% endblock modal %} + {% block inline_javascript %} {% comment %} Script tags with only code, no src (defer by default). To run with a "defer" so that you run inline code: {% endcomment %} - {% endblock inline_javascript %} - + {% endblock inline_javascript %} + {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pages/about.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pages/about.html index 8968a3d4f..3d301eead 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pages/about.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pages/about.html @@ -1 +1,3 @@ -{% raw %}{% extends "base.html" %}{% endraw %} +{% raw %}{% extends "base.html" %} + +{% endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pages/home.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pages/home.html index 8968a3d4f..3d301eead 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pages/home.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/pages/home.html @@ -1 +1,3 @@ -{% raw %}{% extends "base.html" %}{% endraw %} +{% raw %}{% extends "base.html" %} + +{% endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/users/user_detail.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/users/user_detail.html index ee2c4aee9..4e632b015 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/users/user_detail.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/users/user_detail.html @@ -1,35 +1,45 @@ {% raw %}{% extends "base.html" %} + {% 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 %} -
- -
-
- -

{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{{ object.name }}{% endraw %}{% else %}{% raw %}{{ object.username }}{% endraw %}{% endif %}{% raw %}

- {% if object.name %} -

{{ object.name }}

- {% endif %} +
+
+
+

+ {% endraw %} + {% if cookiecutter.username_type == "email" %} + {% raw %}{{ object.name }}{% endraw %} + {% else %} + {% raw %}{{ object.username }}{% endraw %} + {% endif %} + {% raw %} +

+ {% if object.name %}

{{ object.name }}

{% endif %}
- -{% if object == request.user %} - -
- -
- My Info - E-Mail - -
- -
- -{% endif %} - + {% if object == request.user %} + +
+
+ My Info + E-Mail + +
+
+ + {% endif %}
{% endblock content %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/users/user_form.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/users/user_form.html index 65401624a..bd1299a6d 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/users/user_form.html +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/users/user_form.html @@ -1,18 +1,36 @@ {% raw %}{% extends "base.html" %} + {% 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 %} -

{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{{ user.name }}{% endraw %}{% else %}{% raw %}{{ user.username }}{% endraw %}{% endif %}{% raw %}

-
- {% csrf_token %} - {{ form|crispy }} -
-
- -
+

+ {% endraw %} + {% if cookiecutter.username_type == "email" %} + {% raw %}{{ user.name }}{% endraw %} + {% else %} + {% raw %}{{ user.username }}{% endraw %} + {% endif %} + {% raw %} +

+ + {% csrf_token %} + {{ form|crispy }} +
+
+
- -{% endblock %} +
+ +{% endblock content %} {%- endraw %} diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/adapters.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/adapters.py index 0d206fae4..c5c824bda 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/adapters.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/adapters.py @@ -1,16 +1,37 @@ -from typing import Any +from __future__ import annotations + +import typing from allauth.account.adapter import DefaultAccountAdapter from allauth.socialaccount.adapter import DefaultSocialAccountAdapter from django.conf import settings 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): - def is_open_for_signup(self, request: HttpRequest): + def is_open_for_signup(self, request: HttpRequest) -> bool: return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True) 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) + + 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) diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/admin.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/admin.py index d81c0a3b0..a5f89dd67 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/admin.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/admin.py @@ -1,12 +1,18 @@ +from django.conf import settings from django.contrib import 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 {{ cookiecutter.project_slug }}.users.forms import UserAdminChangeForm, UserAdminCreationForm 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) class UserAdmin(auth_admin.UserAdmin): diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_views.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_views.py index 0cd0021ff..2c1027038 100644 --- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_views.py +++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/tests/test_views.py @@ -7,6 +7,7 @@ from django.contrib.sessions.middleware import SessionMiddleware from django.http import HttpRequest, HttpResponseRedirect from django.test import RequestFactory 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.models import User @@ -72,7 +73,7 @@ class TestUserUpdateView: view.form_valid(form) 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: