mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-08-07 21:44:52 +03:00
Merge branch 'cookiecutter:master' into main
This commit is contained in:
commit
255b915f49
15
.github/contributors.json
vendored
15
.github/contributors.json
vendored
|
@ -1523,5 +1523,20 @@
|
|||
"name": "Paul Wulff",
|
||||
"github_login": "mtmpaulwulff",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "Mounir",
|
||||
"github_login": "mounirmesselmeni",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "JAEGYUN JUNG",
|
||||
"github_login": "TGoddessana",
|
||||
"twitter_username": ""
|
||||
},
|
||||
{
|
||||
"name": "Simeon Emanuilov",
|
||||
"github_login": "s-emanuilov",
|
||||
"twitter_username": "s_emanuilov"
|
||||
}
|
||||
]
|
16
.github/dependabot.yml
vendored
16
.github/dependabot.yml
vendored
|
@ -3,6 +3,22 @@
|
|||
|
||||
version: 2
|
||||
updates:
|
||||
# Update Python deps for the template (not the generated project)
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
labels:
|
||||
- "project infrastructure"
|
||||
|
||||
# Update Python deps for the documentation
|
||||
- package-ecosystem: "pip"
|
||||
directory: "docs/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
labels:
|
||||
- "project infrastructure"
|
||||
|
||||
# Update GitHub actions in workflows
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
|
|
|
@ -14,8 +14,6 @@ pin: True
|
|||
label_prs: update
|
||||
|
||||
requirements:
|
||||
- "requirements.txt"
|
||||
- "docs/requirements.txt"
|
||||
- "{{cookiecutter.project_slug}}/requirements/base.txt"
|
||||
- "{{cookiecutter.project_slug}}/requirements/local.txt"
|
||||
- "{{cookiecutter.project_slug}}/requirements/production.txt"
|
||||
|
|
72
CHANGELOG.md
72
CHANGELOG.md
|
@ -3,6 +3,78 @@ All enhancements and patches to Cookiecutter Django will be documented in this f
|
|||
|
||||
<!-- GENERATOR_PLACEHOLDER -->
|
||||
|
||||
## 2024.03.03
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update django-celery-beat to 2.6.0 ([#4899](https://github.com/cookiecutter/cookiecutter-django/pull/4899))
|
||||
|
||||
## 2024.03.01
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Add a maintainer guide to the docs ([#4884](https://github.com/cookiecutter/cookiecutter-django/pull/4884))
|
||||
|
||||
### Updated
|
||||
|
||||
- Auto-update pre-commit hooks ([#4897](https://github.com/cookiecutter/cookiecutter-django/pull/4897))
|
||||
|
||||
- Update ruff to 0.3.0 ([#4896](https://github.com/cookiecutter/cookiecutter-django/pull/4896))
|
||||
|
||||
## 2024.02.28
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix invalid HTML in django-allauth field element template ([#4894](https://github.com/cookiecutter/cookiecutter-django/pull/4894))
|
||||
|
||||
- Fix permissions for media files when served by nginx ([#4889](https://github.com/cookiecutter/cookiecutter-django/pull/4889))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Fix broken "Two scoops of django" link in FAQ ([#4892](https://github.com/cookiecutter/cookiecutter-django/pull/4892))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update redis to 5.0.2 ([#4895](https://github.com/cookiecutter/cookiecutter-django/pull/4895))
|
||||
|
||||
- Update sentry-sdk to 1.40.6 ([#4893](https://github.com/cookiecutter/cookiecutter-django/pull/4893))
|
||||
|
||||
## 2024.02.26
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Allauth elements & MFA ([#4843](https://github.com/cookiecutter/cookiecutter-django/pull/4843))
|
||||
|
||||
### Updated
|
||||
|
||||
- Update pytest to 8.0.2 ([#4890](https://github.com/cookiecutter/cookiecutter-django/pull/4890))
|
||||
|
||||
- Update crispy-bootstrap5 to 2024.2 ([#4891](https://github.com/cookiecutter/cookiecutter-django/pull/4891))
|
||||
|
||||
## 2024.02.24
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update coverage to 7.4.3 ([#4888](https://github.com/cookiecutter/cookiecutter-django/pull/4888))
|
||||
|
||||
## 2024.02.23
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Switch to local imports within app ([#4883](https://github.com/cookiecutter/cookiecutter-django/pull/4883))
|
||||
|
||||
- Install ruff extension in `devcontainer.json` ([#4887](https://github.com/cookiecutter/cookiecutter-django/pull/4887))
|
||||
|
||||
### Updated
|
||||
|
||||
- Bump webpack-dev-server to 5.0.2 ([#4875](https://github.com/cookiecutter/cookiecutter-django/pull/4875))
|
||||
|
||||
## 2024.02.21
|
||||
|
||||
|
||||
|
|
|
@ -1048,6 +1048,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JAEGYUN JUNG</td>
|
||||
<td>
|
||||
<a href="https://github.com/TGoddessana">TGoddessana</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jakub Boukal</td>
|
||||
<td>
|
||||
|
@ -1552,6 +1559,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mounir</td>
|
||||
<td>
|
||||
<a href="https://github.com/mounirmesselmeni">mounirmesselmeni</a>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>mozillazg</td>
|
||||
<td>
|
||||
|
@ -1832,6 +1846,13 @@ Listed in alphabetical order.
|
|||
</td>
|
||||
<td>shywn_mrk</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simeon Emanuilov</td>
|
||||
<td>
|
||||
<a href="https://github.com/s-emanuilov">s-emanuilov</a>
|
||||
</td>
|
||||
<td>s_emanuilov</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Simon Rey</td>
|
||||
<td>
|
||||
|
|
|
@ -22,6 +22,6 @@ TODO
|
|||
Why doesn't this follow the layout from Two Scoops of Django?
|
||||
-------------------------------------------------------------
|
||||
|
||||
You may notice that some elements of this project do not exactly match what we describe in chapter 3 of `Two Scoops of Django 1.11`_. The reason for that is this project, amongst other things, serves as a test bed for trying out new ideas and concepts. Sometimes they work, sometimes they don't, but the end result is that it won't necessarily match precisely what is described in the book I co-authored.
|
||||
You may notice that some elements of this project do not exactly match what we describe in chapter 3 of `Two Scoops of Django 3.x`_. The reason for that is this project, amongst other things, serves as a test bed for trying out new ideas and concepts. Sometimes they work, sometimes they don't, but the end result is that it won't necessarily match precisely what is described in the book I co-authored.
|
||||
|
||||
.. _Two Scoops of Django 1.11: https://www.feldroy.com/collections/django/products/two-scoops-of-django-1-11
|
||||
.. _Two Scoops of Django 3.x: https://www.feldroy.com/books/two-scoops-of-django-3-x
|
||||
|
|
|
@ -28,6 +28,7 @@ Contents
|
|||
faq
|
||||
troubleshooting
|
||||
contributing
|
||||
maintainer-guide
|
||||
|
||||
Indices and tables
|
||||
------------------
|
||||
|
|
104
docs/maintainer-guide.md
Normal file
104
docs/maintainer-guide.md
Normal file
|
@ -0,0 +1,104 @@
|
|||
# Maintainer guide
|
||||
|
||||
This document is intended for maintainers of the template.
|
||||
|
||||
## Automated updates
|
||||
|
||||
We use 2 separate services to keep our dependencies up-to-date:
|
||||
|
||||
- Dependabot, which manages updates of Python deps of the template, GitHub actions, npm packages and Docker images.
|
||||
- PyUp, which manages the Python deps for the generated project.
|
||||
|
||||
We don't use Dependabot for the generated project deps because our requirements files are templated, and Dependabot fails to parse them. PyUp is -AFAIK- the only service out there that supports having Jinja tags in the requirements file.
|
||||
|
||||
Updates for the template should be labelled as `project infrastructure` while the ones about the generated project should be labelled as `update`. This is use to work in conjunction with our changelog script (see later).
|
||||
|
||||
## Automation scripts
|
||||
|
||||
We have a few workflows which have been automated over time. They usually run using GitHub actions and might need a few small manual actions to work nicely. Some have a few limitations which we should document here.
|
||||
|
||||
### CI
|
||||
|
||||
`ci.yml`
|
||||
|
||||
The CI workflow tries to cover 2 main aspects of the template:
|
||||
|
||||
- Check all combinations to make sure that valid files are generated with no major linting issues. Issues which are fixed by an auto-formatter after generation aren't considered major, and only aim for best effort. This is under the `test` job.
|
||||
- Run more in-depth tests on a few combinations, by installing dependencies, running type checker and the test suite of the generated project. We try to cover docker (`docker` job) and non-docker (`bare` job) setups.
|
||||
|
||||
We also run the deployment checks, but we don't do much more beyond that for testing the production setup.
|
||||
|
||||
### Django issue checker
|
||||
|
||||
`django-issue-checker.yml`
|
||||
|
||||
This workflow runs daily, on schedule, and checks if there is a new major version of Django (not in the pure SemVer sense) released that we are not running, and list our dependencies compatibility.
|
||||
|
||||
For example, at time of writing, we use Django 4.2, but the latest version of Django is 5.0, so the workflow created a ["Django 5.0" issue](https://github.com/cookiecutter/cookiecutter-django/issues/4724) in GitHub, with a compatibility table and keeps it up to date every day.
|
||||
|
||||
#### Limitations
|
||||
|
||||
Here are a few current and past limitations of the script
|
||||
|
||||
- When a new dependency is added to the template, the script fails to update an existing issue
|
||||
- Not sure what happens when a deps is removed
|
||||
- ~~Unable to parse classifiers without minor version~~
|
||||
- ~~Creates an issue even if we are on the latest version~~
|
||||
|
||||
### Issue manager
|
||||
|
||||
`issue-manager.yml`
|
||||
|
||||
A workflow that uses [Sebastian Ramirez' issue-manager](https://github.com/tiangolo/issue-manager) to help us automate issue management. The tag line from the repo explains it well:
|
||||
|
||||
> Automatically close issues or Pull Requests that have a label, after a custom delay, if no one replies back.
|
||||
|
||||
It runs on a schedule as well as when some actions are taken on issues and pull requests.
|
||||
|
||||
We wait 10 days before closing issues, and we have a few customised reasons, which are configured in the workflow itself. The config should be fairly self-explanatory.
|
||||
|
||||
### Pre-commit auto-update
|
||||
|
||||
`pre-commit-autoupdate.yml`
|
||||
|
||||
Run daily, to do `pre-commit autoupdate` on the template as well as the generated project, and opens a pull request with the changes.
|
||||
|
||||
#### Limitations
|
||||
|
||||
- The PR is open as GitHub action which means that CI does NOT run. The documentation for create-pull-request action [explains why](https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#triggering-further-workflow-runs).
|
||||
- Some hooks are also installed as local dependencies (via `requirements/local.txt`), but these are updated separately via PyUP.
|
||||
|
||||
### Update changelog
|
||||
|
||||
`update-changelog.yml`
|
||||
|
||||
Run daily at 2AM to update our changelog and create a GitHub release. This runs a custom script which:
|
||||
|
||||
- List all pull requests merged the day before
|
||||
- The release name is calendar based, so `YYYY.MM.DD`
|
||||
- For each PR:
|
||||
- Get the PR title to summarize the change
|
||||
- Look at the PR labels to classify it in a section of the release notes:
|
||||
- anything labelled `project infrastructure` is excluded
|
||||
- label `update` goes in section "Updated"
|
||||
- label `bug` goes in section "Fixed"
|
||||
- label `docs` goes in section "Documentation"
|
||||
- Default to section "Changed"
|
||||
|
||||
With that in mind, when merging changes, it's a good idea to set the labels and rename the PR title to give a good summary of the change, in the context of the changelog.
|
||||
|
||||
#### Limitations
|
||||
|
||||
- Dependabot updates for npm & Docker have a verbose title, try to rename them to be more readable: `Bump webpack-dev-server from 4.15.1 to 5.0.2 in /{{cookiecutter.project_slug}}` -> `Bump webpack-dev-server to 5.0.2`
|
||||
- ~~Dependencies updates for the template repo (tox, cookiecutter, etc...) don't need to appear in changelog, and need to be labelled as `project infrastructure` manually. By default, they come from PyUp labelled as `update`.~~
|
||||
|
||||
### Update contributors
|
||||
|
||||
`update-contributors.yml`
|
||||
|
||||
Runs on each push to master branch. List the 5 most recently merged pull requests and extract their author. If any of the authors is a new one, updates the `.github/contributors.json`, regenerate the `CONTRIBUTORS.md` from it, and push back the changes to master.
|
||||
|
||||
#### Limitations
|
||||
|
||||
- If you merge a pull request from a new contributor, and merge another one right after, the push to master will fail as the remote will be out of date.
|
||||
- If you merge more than 5 pull requests in a row like this, the new contributor might fail to be added.
|
|
@ -4,7 +4,7 @@ binaryornot==0.4.4
|
|||
|
||||
# Code quality
|
||||
# ------------------------------------------------------------------------------
|
||||
ruff==0.2.2
|
||||
ruff==0.3.0
|
||||
django-upgrade==1.16.0
|
||||
djlint==1.34.1
|
||||
pre-commit==3.6.2
|
||||
|
@ -12,7 +12,7 @@ pre-commit==3.6.2
|
|||
# Testing
|
||||
# ------------------------------------------------------------------------------
|
||||
tox==4.13.0
|
||||
pytest==8.0.1
|
||||
pytest==8.1.0
|
||||
pytest-xdist==3.5.0
|
||||
pytest-cookies==0.7.0
|
||||
pytest-instafail==0.5.0
|
||||
|
|
|
@ -40,8 +40,8 @@ def iter_recent_authors():
|
|||
"""
|
||||
Fetch users who opened recently merged pull requests.
|
||||
|
||||
Use Github API to fetch recent authors rather than
|
||||
git CLI to work with Github usernames.
|
||||
Use GitHub API to fetch recent authors rather than
|
||||
git CLI to work with GitHub usernames.
|
||||
"""
|
||||
repo = Github(login_or_token=GITHUB_TOKEN, per_page=5).get_repo(GITHUB_REPO)
|
||||
recent_pulls = repo.get_pulls(state="closed", sort="updated", direction="desc").get_page(0)
|
||||
|
|
2
setup.py
2
setup.py
|
@ -5,7 +5,7 @@ except ImportError:
|
|||
from distutils.core import setup
|
||||
|
||||
# We use calendar versioning
|
||||
version = "2024.02.21"
|
||||
version = "2024.03.03"
|
||||
|
||||
with open("README.md") as readme_file:
|
||||
long_description = readme_file.read()
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
"analysis.typeCheckingMode": "basic",
|
||||
"defaultInterpreterPath": "/usr/local/bin/python",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": true
|
||||
"source.organizeImports": "always"
|
||||
},
|
||||
"editor.defaultFormatter": "charliermarsh.ruff",
|
||||
"languageServer": "Pylance",
|
||||
|
@ -54,8 +54,7 @@
|
|||
// python
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"ms-python.isort",
|
||||
"ms-python.black-formatter",
|
||||
"charliermarsh.ruff",
|
||||
// django
|
||||
"batisteo.vscode-django"
|
||||
]
|
||||
|
|
|
@ -35,7 +35,7 @@ repos:
|
|||
|
||||
# Run the Ruff linter.
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.2.2
|
||||
rev: v0.3.0
|
||||
hooks:
|
||||
# Linter
|
||||
- id: ruff
|
||||
|
|
|
@ -117,7 +117,7 @@ COPY --chown=django:django . ${APP_HOME}
|
|||
{%- endif %}
|
||||
|
||||
# make django owner of the WORKDIR directory as well.
|
||||
RUN chown django:django ${APP_HOME}
|
||||
RUN chown -R django:django ${APP_HOME}
|
||||
|
||||
USER django
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ THIRD_PARTY_APPS = [
|
|||
"crispy_bootstrap5",
|
||||
"allauth",
|
||||
"allauth.account",
|
||||
"allauth.mfa",
|
||||
"allauth.socialaccount",
|
||||
{%- if cookiecutter.use_celery == 'y' %}
|
||||
"django_celery_beat",
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"webpack": "^5.65.0",
|
||||
"webpack-bundle-tracker": "^3.0.1",
|
||||
"webpack-cli": "^5.0.1",
|
||||
"webpack-dev-server": "^4.6.0",
|
||||
"webpack-dev-server": "^5.0.2",
|
||||
"webpack-merge": "^5.8.0"
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
@ -11,13 +11,13 @@ argon2-cffi==23.1.0 # https://github.com/hynek/argon2_cffi
|
|||
{%- if cookiecutter.use_whitenoise == 'y' %}
|
||||
whitenoise==6.6.0 # https://github.com/evansd/whitenoise
|
||||
{%- endif %}
|
||||
redis==5.0.1 # https://github.com/redis/redis-py
|
||||
redis==5.0.2 # https://github.com/redis/redis-py
|
||||
{%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %}
|
||||
hiredis==2.3.2 # https://github.com/redis/hiredis-py
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_celery == "y" %}
|
||||
celery==5.3.6 # pyup: < 6.0 # https://github.com/celery/celery
|
||||
django-celery-beat==2.5.0 # https://github.com/celery/django-celery-beat
|
||||
django-celery-beat==2.6.0 # https://github.com/celery/django-celery-beat
|
||||
{%- if cookiecutter.use_docker == 'y' %}
|
||||
flower==2.0.1 # https://github.com/mher/flower
|
||||
{%- endif %}
|
||||
|
@ -28,12 +28,12 @@ uvicorn[standard]==0.27.1 # https://github.com/encode/uvicorn
|
|||
|
||||
# Django
|
||||
# ------------------------------------------------------------------------------
|
||||
django==4.2.10 # pyup: < 5.0 # https://www.djangoproject.com/
|
||||
django==4.2.11 # pyup: < 5.0 # https://www.djangoproject.com/
|
||||
django-environ==0.11.2 # https://github.com/joke2k/django-environ
|
||||
django-model-utils==4.4.0 # https://github.com/jazzband/django-model-utils
|
||||
django-allauth==0.61.1 # https://github.com/pennersr/django-allauth
|
||||
django-allauth[mfa]==0.61.1 # https://github.com/pennersr/django-allauth
|
||||
django-crispy-forms==2.1 # https://github.com/django-crispy-forms/django-crispy-forms
|
||||
crispy-bootstrap5==2023.10 # https://github.com/django-crispy-forms/crispy-bootstrap5
|
||||
crispy-bootstrap5==2024.2 # https://github.com/django-crispy-forms/crispy-bootstrap5
|
||||
{%- if cookiecutter.frontend_pipeline == 'Django Compressor' %}
|
||||
django-compressor==4.4 # https://github.com/django-compressor/django-compressor
|
||||
{%- endif %}
|
||||
|
|
|
@ -15,7 +15,7 @@ watchfiles==0.21.0 # https://github.com/samuelcolvin/watchfiles
|
|||
# ------------------------------------------------------------------------------
|
||||
mypy==1.7.1 # https://github.com/python/mypy
|
||||
django-stubs[compatible-mypy]==4.2.7 # https://github.com/typeddjango/django-stubs
|
||||
pytest==8.0.1 # https://github.com/pytest-dev/pytest
|
||||
pytest==8.1.0 # https://github.com/pytest-dev/pytest
|
||||
pytest-sugar==1.0.0 # https://github.com/Frozenball/pytest-sugar
|
||||
{%- if cookiecutter.use_drf == "y" %}
|
||||
djangorestframework-stubs[compatible-mypy]==3.14.5 # https://github.com/typeddjango/djangorestframework-stubs
|
||||
|
@ -28,8 +28,8 @@ sphinx-autobuild==2024.2.4 # https://github.com/GaretJax/sphinx-autobuild
|
|||
|
||||
# Code quality
|
||||
# ------------------------------------------------------------------------------
|
||||
ruff==0.2.2 # https://github.com/astral-sh/ruff
|
||||
coverage==7.4.1 # https://github.com/nedbat/coveragepy
|
||||
ruff==0.3.0 # https://github.com/astral-sh/ruff
|
||||
coverage==7.4.3 # https://github.com/nedbat/coveragepy
|
||||
djlint==1.34.1 # https://github.com/Riverside-Healthcare/djLint
|
||||
pre-commit==3.6.2 # https://github.com/pre-commit/pre-commit
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ psycopg[c]==3.1.18 # https://github.com/psycopg/psycopg
|
|||
Collectfast==2.2.0 # https://github.com/antonagestam/collectfast
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_sentry == "y" %}
|
||||
sentry-sdk==1.40.5 # https://github.com/getsentry/sentry-python
|
||||
sentry-sdk==1.40.6 # https://github.com/getsentry/sentry-python
|
||||
{%- endif %}
|
||||
{%- if cookiecutter.use_docker == "n" and cookiecutter.windows == "y" %}
|
||||
hiredis==2.3.2 # https://github.com/redis/hiredis-py
|
||||
|
|
|
@ -1 +1 @@
|
|||
python-3.11.7
|
||||
python-3.11.8
|
||||
|
|
|
@ -6,13 +6,16 @@ module.exports = merge(commonConfig, {
|
|||
devtool: 'inline-source-map',
|
||||
devServer: {
|
||||
port: 3000,
|
||||
proxy: {
|
||||
proxy: [
|
||||
{
|
||||
context: ['/'],
|
||||
{%- if cookiecutter.use_docker == 'n' %}
|
||||
'/': 'http://0.0.0.0:8000',
|
||||
target: 'http://0.0.0.0:8000',
|
||||
{%- else %}
|
||||
'/': 'http://django:8000',
|
||||
target: 'http://django:8000',
|
||||
{%- endif %}
|
||||
},
|
||||
],
|
||||
client: {
|
||||
overlay: {
|
||||
errors: true,
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Account Inactive" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Account Inactive" %}</h1>
|
||||
<p>{% translate "This account is inactive." %}</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,14 +0,0 @@
|
|||
{% raw %}{% extends "base.html" %}
|
||||
|
||||
{% block title %}
|
||||
{% block head_title %}
|
||||
{% endblock head_title %}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-6 offset-md-3">
|
||||
{% block inner %}{% endblock inner %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
{%- endraw %}
|
|
@ -0,0 +1,11 @@
|
|||
{% raw %}{% extends "account/base_manage.html" %}
|
||||
|
||||
{% block main %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock main %}{% endraw %}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
{% raw %}
|
||||
{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Account" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "E-mail Addresses" %}</h1>
|
||||
{% if user.emailaddress_set.all %}
|
||||
<p>{% translate "The following e-mail addresses are associated with your account:" %}</p>
|
||||
<form action="{% url 'account_email' %}" class="email_list" method="post">
|
||||
{% csrf_token %}
|
||||
<fieldset class="blockLabels">
|
||||
{% for emailaddress in user.emailaddress_set.all %}
|
||||
<div class="radio">
|
||||
<label for="email_radio_{{ forloop.counter }}"
|
||||
class="{% if emailaddress.primary %}primary_email{% endif %}">
|
||||
<input id="email_radio_{{ forloop.counter }}"
|
||||
type="radio"
|
||||
name="email"
|
||||
{% if emailaddress.primary or user.emailaddress_set.count == 1 %}checked="checked"{% endif %}
|
||||
value="{{ emailaddress.email }}" />
|
||||
{{ emailaddress.email }}
|
||||
{% if emailaddress.verified %}
|
||||
<span class="verified">{% translate "Verified" %}</span>
|
||||
{% else %}
|
||||
<span class="unverified">{% translate "Unverified" %}</span>
|
||||
{% endif %}
|
||||
{% if emailaddress.primary %}
|
||||
<span class="primary">{% translate "Primary" %}</span>
|
||||
{% endif %}
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="form-group">
|
||||
<button class="secondaryAction btn btn-primary"
|
||||
type="submit"
|
||||
name="action_primary">{% translate "Make Primary" %}</button>
|
||||
<button class="secondaryAction btn btn-primary"
|
||||
type="submit"
|
||||
name="action_send">{% translate "Re-send Verification" %}</button>
|
||||
<button class="primaryAction btn btn-primary"
|
||||
type="submit"
|
||||
name="action_remove">{% translate "Remove" %}</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
{% else %}
|
||||
<p>
|
||||
<strong>{% translate "Warning:" %}</strong> {% translate "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<h2>{% translate "Add E-mail Address" %}</h2>
|
||||
<form method="post" action="{% url 'account_email' %}" class="add_email">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button class="btn btn-primary" name="action_add" type="submit">{% translate "Add E-mail" %}</button>
|
||||
</form>
|
||||
{% endblock inner %}
|
||||
{% block inline_javascript %}
|
||||
{{ block.super }}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
const message = "{% translate 'Do you really want to remove the selected e-mail address?' %}";
|
||||
const actions = document.getElementsByName('action_remove');
|
||||
if (actions.length) {
|
||||
actions[0].addEventListener("click", function(e) {
|
||||
if (!confirm(message)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
Array.from(document.getElementsByClassName('form-group')).forEach(x => x.classList.remove('row'));
|
||||
});
|
||||
</script>
|
||||
{% endblock inline_javascript %}
|
||||
{%- endraw %}
|
|
@ -1,28 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load account %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Confirm E-mail Address" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Confirm E-mail Address" %}</h1>
|
||||
{% if confirmation %}
|
||||
{% user_display confirmation.email_address.user as user_display %}
|
||||
<p>
|
||||
{% blocktranslate with confirmation.email_address.email as email %}Please confirm that <a href="mailto:{{ email }}">{{ email }}</a> is an e-mail address for user {{ user_display }}.{% endblocktranslate %}
|
||||
</p>
|
||||
<form method="post"
|
||||
action="{% url 'account_confirm_email' confirmation.key %}">
|
||||
{% csrf_token %}
|
||||
<button class="btn btn-primary" type="submit">{% translate "Confirm" %}</button>
|
||||
</form>
|
||||
{% else %}
|
||||
{% url 'account_email' as email_url %}
|
||||
<p>
|
||||
{% blocktranslate %}This e-mail confirmation link expired or is invalid. Please <a href="{{ email_url }}">issue a new e-mail confirmation request</a>.{% endblocktranslate %}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,53 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load account socialaccount %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Sign In" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Sign In" %}</h1>
|
||||
{% get_providers as socialaccount_providers %}
|
||||
{% if socialaccount_providers %}
|
||||
<p>
|
||||
{% translate "Please sign in with one of your existing third party accounts:" %}
|
||||
{% if ACCOUNT_ALLOW_REGISTRATION %}
|
||||
{% blocktranslate trimmed %}
|
||||
Or, <a href="{{ signup_url }}">sign up</a>
|
||||
for a {{ site_name }} account and sign in below:
|
||||
{% endblocktranslate %}
|
||||
{% endif %}
|
||||
</p>
|
||||
<div class="socialaccount_ballot">
|
||||
<ul class="socialaccount_providers">
|
||||
{% include "socialaccount/snippets/provider_list.html" with process="login" %}
|
||||
</ul>
|
||||
<div class="login-or">{% translate "or" %}</div>
|
||||
</div>
|
||||
{% include "socialaccount/snippets/login_extra.html" %}
|
||||
{% else %}
|
||||
{% if ACCOUNT_ALLOW_REGISTRATION %}
|
||||
<p>
|
||||
{% blocktranslate trimmed %}
|
||||
If you have not created an account yet, then please
|
||||
<a href="{{ signup_url }}">sign up</a> first.
|
||||
{% endblocktranslate %}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<form class="login" method="post" action="{% url 'account_login' %}">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
{% if redirect_field_value %}
|
||||
<input type="hidden"
|
||||
name="{{ redirect_field_name }}"
|
||||
value="{{ redirect_field_value }}" />
|
||||
{% endif %}
|
||||
<a class="button secondaryAction"
|
||||
href="{% url 'account_reset_password' %}">{% translate "Forgot Password?" %}</a>
|
||||
<button class="primaryAction btn btn-primary" type="submit">{% translate "Sign In" %}</button>
|
||||
</form>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,21 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Sign Out" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Sign Out" %}</h1>
|
||||
<p>{% translate "Are you sure you want to sign out?" %}</p>
|
||||
<form method="post" action="{% url 'account_logout' %}">
|
||||
{% csrf_token %}
|
||||
{% if redirect_field_value %}
|
||||
<input type="hidden"
|
||||
name="{{ redirect_field_name }}"
|
||||
value="{{ redirect_field_value }}" />
|
||||
{% endif %}
|
||||
<button class="btn btn-danger" type="submit">{% translate "Sign Out" %}</button>
|
||||
</form>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,19 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Change Password" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Change Password" %}</h1>
|
||||
<form method="post"
|
||||
action="{% url 'account_change_password' %}"
|
||||
class="password_change">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button class="btn btn-primary" type="submit" name="action">{% translate "Change Password" %}</button>
|
||||
</form>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,29 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load account %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Password Reset" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Password Reset" %}</h1>
|
||||
{% if user.is_authenticated %}
|
||||
{% include "account/snippets/already_logged_in.html" %}
|
||||
{% endif %}
|
||||
<p>
|
||||
{% translate "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}
|
||||
</p>
|
||||
<form method="post"
|
||||
action="{% url 'account_reset_password' %}"
|
||||
class="password_reset">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<input class="btn btn-primary"
|
||||
type="submit"
|
||||
value="{% translate 'Reset My Password' %}" />
|
||||
</form>
|
||||
<p>{% blocktranslate %}Please contact us if you have any trouble resetting your password.{% endblocktranslate %}</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,18 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load account %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Password Reset" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Password Reset" %}</h1>
|
||||
{% if user.is_authenticated %}
|
||||
{% include "account/snippets/already_logged_in.html" %}
|
||||
{% endif %}
|
||||
<p>
|
||||
{% blocktranslate %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}
|
||||
</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,37 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Change Password" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% if token_fail %}
|
||||
{% translate "Bad Token" %}
|
||||
{% else %}
|
||||
{% translate "Change Password" %}
|
||||
{% endif %}
|
||||
</h1>
|
||||
{% if token_fail %}
|
||||
{% url 'account_reset_password' as passwd_reset_url %}
|
||||
<p>
|
||||
{% blocktranslate %}The password reset link was invalid, possibly because it has already been used. Please request a <a href="{{ passwd_reset_url }}">new password reset</a>.{% endblocktranslate %}
|
||||
</p>
|
||||
{% else %}
|
||||
{% if form %}
|
||||
<form method="post" action=".">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<input class="btn btn-primary"
|
||||
type="submit"
|
||||
name="action"
|
||||
value="{% translate 'change password' %}" />
|
||||
</form>
|
||||
{% else %}
|
||||
<p>{% translate "Your password is now changed." %}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,12 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Change Password" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Change Password" %}</h1>
|
||||
<p>{% translate "Your password is now changed." %}</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,22 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Set Password" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Set Password" %}</h1>
|
||||
<form method="post"
|
||||
action="{% url 'account_set_password' %}"
|
||||
class="password_set">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<input class="btn btn-primary"
|
||||
type="submit"
|
||||
name="action"
|
||||
value="{% translate 'Set Password' %}" />
|
||||
</form>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,28 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Signup" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Sign Up" %}</h1>
|
||||
<p>
|
||||
{% blocktranslate %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktranslate %}
|
||||
</p>
|
||||
<form class="signup"
|
||||
id="signup_form"
|
||||
method="post"
|
||||
action="{% url 'account_signup' %}">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
{% if redirect_field_value %}
|
||||
<input type="hidden"
|
||||
name="{{ redirect_field_name }}"
|
||||
value="{{ redirect_field_value }}" />
|
||||
{% endif %}
|
||||
<button class="btn btn-primary" type="submit">{% translate "Sign Up" %} »</button>
|
||||
</form>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,12 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Sign Up Closed" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Sign Up Closed" %}</h1>
|
||||
<p>{% translate "We are sorry, but the sign up is currently closed." %}</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,14 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Verify Your E-mail Address" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Verify Your E-mail Address" %}</h1>
|
||||
<p>
|
||||
{% blocktranslate %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktranslate %}
|
||||
</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -1,25 +0,0 @@
|
|||
{% raw %}{% extends "account/base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block head_title %}
|
||||
{% translate "Verify Your E-mail Address" %}
|
||||
{% endblock head_title %}
|
||||
{% block inner %}
|
||||
<h1>{% translate "Verify Your E-mail Address" %}</h1>
|
||||
{% url 'account_email' as email_url %}
|
||||
<p>
|
||||
{% blocktranslate %}This part of the site requires us to verify that
|
||||
you are who you claim to be. For this purpose, we require that you
|
||||
verify ownership of your e-mail address. {% endblocktranslate %}
|
||||
</p>
|
||||
<p>
|
||||
{% 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 %}
|
||||
</p>
|
||||
<p>
|
||||
{% blocktranslate %}<strong>Note:</strong> you can still <a href="{{ email_url }}">change your e-mail address</a>.{% endblocktranslate %}
|
||||
</p>
|
||||
{% endblock inner %}
|
||||
{%- endraw %}
|
|
@ -0,0 +1,7 @@
|
|||
{% raw %}{% load i18n %}
|
||||
{% load allauth %}
|
||||
|
||||
<div class="alert alert-error">
|
||||
{% slot message %}
|
||||
{% endslot %}
|
||||
</div>{% endraw %}
|
|
@ -0,0 +1,6 @@
|
|||
{% raw %}{% load allauth %}
|
||||
|
||||
<span class="badge {% if 'success' in attrs.tags %}bg-success{% endif %} {% if 'warning' in attrs.tags %}bg-warning{% endif %} {% if 'secondary' in attrs.tags %}bg-secondary{% endif %} {% if 'danger' in attrs.tags %}bg-danger{% endif %} {% if 'primary' in attrs.tags %}bg-primary{% endif %}">
|
||||
{% slot %}
|
||||
{% endslot %}
|
||||
</span>{% endraw %}
|
|
@ -0,0 +1,20 @@
|
|||
{% raw %}{% load allauth %}
|
||||
|
||||
{% comment %} djlint:off {% endcomment %}
|
||||
<{% if attrs.href %}a href="{{ attrs.href }}"{% else %}button{% endif %}
|
||||
{% if attrs.form %}form="{{ attrs.form }}"{% endif %}
|
||||
{% if attrs.id %}id="{{ attrs.id }}"{% endif %}
|
||||
{% if attrs.name %}name="{{ attrs.name }}"{% endif %}
|
||||
{% if attrs.type %}type="{{ attrs.type }}"{% endif %}
|
||||
class="btn
|
||||
{% if 'success' in attrs.tags %}btn-success
|
||||
{% elif 'warning' in attrs.tags %}btn-warning
|
||||
{% elif 'secondary' in attrs.tags %}btn-secondary
|
||||
{% elif 'danger' in attrs.tags %}btn-danger
|
||||
{% elif 'primary' in attrs.tags %}btn-primary
|
||||
{% else %}btn-primary
|
||||
{% endif %}"
|
||||
>
|
||||
{% slot %}
|
||||
{% endslot %}
|
||||
</{% if attrs.href %}a{% else %}button{% endif %}>{% endraw %}
|
|
@ -0,0 +1,66 @@
|
|||
{% raw %}{% load allauth %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% if attrs.type == "textarea" %}
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-10">
|
||||
<label for="{{ attrs.id }}">
|
||||
{% slot label %}
|
||||
{% endslot %}
|
||||
</label>
|
||||
</div>
|
||||
<textarea {% if attrs.required %}required{% endif %}
|
||||
{% if attrs.rows %}rows="{{ attrs.rows }}"{% endif %}
|
||||
{% if attrs.disabled %}disabled{% endif %}
|
||||
{% if attrs.readonly %}readonly{% endif %}
|
||||
{% if attrs.checked %}checked{% endif %}
|
||||
{% if attrs.name %}name="{{ attrs.name }}"{% endif %}
|
||||
{% if attrs.id %}id="{{ attrs.id }}"{% endif %}
|
||||
{% if attrs.placeholder %}placeholder="{{ attrs.placeholder }}"{% endif %}
|
||||
class="form-control">{% slot value %}{% endslot %}</textarea>
|
||||
</div>
|
||||
{% elif attrs.type == "radio" %}
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check">
|
||||
<input {% if attrs.required %}required{% endif %}
|
||||
{% if attrs.disabled %}disabled{% endif %}
|
||||
{% if attrs.readonly %}readonly{% endif %}
|
||||
{% if attrs.checked %}checked{% endif %}
|
||||
{% if attrs.name %}name="{{ attrs.name }}"{% endif %}
|
||||
{% if attrs.id %}id="{{ attrs.id }}"{% endif %}
|
||||
{% if attrs.placeholder %}placeholder="{{ attrs.placeholder }}"{% endif %}
|
||||
{% if attrs.autocomplete %}autocomplete="{{ attrs.autocomplete }}"{% endif %}
|
||||
value="{{ attrs.value|default_if_none:"" }}"
|
||||
type="{{ attrs.type }}" />
|
||||
<label class="form-check-label" for="{{ attrs.id }}">
|
||||
{% slot label %}
|
||||
{% endslot %}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="col-sm-10">
|
||||
<label for="{{ attrs.id }}">
|
||||
{% slot label %}
|
||||
{% endslot %}
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<input {% if attrs.required %}required{% endif %}
|
||||
{% if attrs.disabled %}disabled{% endif %}
|
||||
{% if attrs.readonly %}readonly{% endif %}
|
||||
{% if attrs.checked %}checked{% endif %}
|
||||
{% if attrs.name %}name="{{ attrs.name }}"{% endif %}
|
||||
{% if attrs.id %}id="{{ attrs.id }}"{% endif %}
|
||||
{% if attrs.placeholder %}placeholder="{{ attrs.placeholder }}"{% endif %}
|
||||
{% if attrs.autocomplete %}autocomplete="{{ attrs.autocomplete }}"{% endif %}
|
||||
value="{{ attrs.value|default_if_none:"" }}"
|
||||
type="{{ attrs.type }}"
|
||||
class="form-control" />
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if slots.help_text %}
|
||||
<div class="form-text">{% slot help_text %}{% endslot %}</div>
|
||||
{% endif %}{% endraw %}
|
|
@ -0,0 +1,3 @@
|
|||
{% raw %}{% load crispy_forms_tags %}
|
||||
|
||||
{{ attrs.form|crispy }}{% endraw %}
|
|
@ -0,0 +1,19 @@
|
|||
{% raw %}{% load allauth %}
|
||||
|
||||
<section>
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">
|
||||
{% slot title %}
|
||||
{% endslot %}
|
||||
</h2>
|
||||
{% slot body %}
|
||||
{% endslot %}
|
||||
{% if slots.actions %}
|
||||
<ul>
|
||||
{% for action in slots.actions %}<li>{{ action }}</li>{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</section>{% endraw %}
|
|
@ -0,0 +1,6 @@
|
|||
{% raw %}{% load allauth %}
|
||||
|
||||
<table class="table">
|
||||
{% slot %}
|
||||
{% endslot %}
|
||||
</table>{% endraw %}
|
|
@ -0,0 +1,29 @@
|
|||
{% raw %}{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% block bodyclass %}bg-light{% endblock bodyclass %}
|
||||
|
||||
{% block css %}{{ block.super }}{% endblock css %}
|
||||
{% block title %}
|
||||
{% block head_title %}
|
||||
{% trans "Sign In" %}
|
||||
{% endblock head_title %}
|
||||
{% endblock title %}
|
||||
{% block body %}
|
||||
<div class="d-flex justify-content-center h-100 py-4">
|
||||
<div class="col-md-4 py-4 my-4 px-4">
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-dismissible {% if message.tags %}alert-{{ message.tags }}{% endif %}">
|
||||
{{ message }}
|
||||
<button type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="alert"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock body %}{% endraw %}
|
|
@ -0,0 +1,6 @@
|
|||
{% raw %}{% extends "base.html" %}
|
||||
|
||||
{% block main %}
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
{% endblock main %}{% endraw %}
|
|
@ -111,7 +111,8 @@
|
|||
{% raw %}
|
||||
{% endblock javascript %}
|
||||
</head>
|
||||
<body>
|
||||
<body class="{% block bodyclass %}{% endblock bodyclass %}">
|
||||
{% block body %}
|
||||
<div class="mb-1">
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-light">
|
||||
<div class="container-fluid">
|
||||
|
@ -171,10 +172,14 @@
|
|||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% block main %}
|
||||
{% block content %}
|
||||
<p>Use this document as a way to quick start any new project.</p>
|
||||
{% endblock content %}
|
||||
{% endblock main %}
|
||||
|
||||
</div>
|
||||
{% endblock body %}
|
||||
<!-- /container -->
|
||||
{% block modal %}
|
||||
{% endblock modal %}
|
||||
|
|
|
@ -41,6 +41,9 @@
|
|||
<a class="btn btn-primary"
|
||||
href="{% url 'account_email' %}"
|
||||
role="button">E-Mail</a>
|
||||
<a class="btn btn-primary"
|
||||
href="{% url 'mfa_index' %}"
|
||||
role="button">MFA</a>
|
||||
<!-- Your Stuff: Custom user template urls -->
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -4,9 +4,9 @@ from django.contrib.auth import admin as auth_admin
|
|||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from {{ cookiecutter.project_slug }}.users.forms import UserAdminChangeForm
|
||||
from {{ cookiecutter.project_slug }}.users.forms import UserAdminCreationForm
|
||||
from {{ cookiecutter.project_slug }}.users.models import User
|
||||
from .forms import UserAdminChangeForm
|
||||
from .forms import UserAdminCreationForm
|
||||
from .models import User
|
||||
|
||||
if settings.DJANGO_ADMIN_FORCE_ALLAUTH:
|
||||
# Force the `admin` sign in process to go through the `django-allauth` workflow:
|
||||
|
|
|
@ -6,7 +6,7 @@ from django.forms import EmailField
|
|||
{%- endif %}
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from {{ cookiecutter.project_slug }}.users.models import User
|
||||
from .models import User
|
||||
|
||||
|
||||
class UserAdminChangeForm(admin_forms.UserChangeForm):
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.contrib.auth.hashers import make_password
|
|||
from django.contrib.auth.models import UserManager as DjangoUserManager
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from {{ cookiecutter.project_slug }}.users.models import User # noqa: F401
|
||||
from .models import User # noqa: F401
|
||||
|
||||
|
||||
class UserManager(DjangoUserManager["User"]):
|
||||
|
|
|
@ -11,7 +11,7 @@ from django.urls import reverse
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
{%- if cookiecutter.username_type == "email" %}
|
||||
|
||||
from {{ cookiecutter.project_slug }}.users.managers import UserManager
|
||||
from .managers import UserManager
|
||||
{%- endif %}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from celery import shared_task
|
||||
|
||||
from {{ cookiecutter.project_slug }}.users.models import User
|
||||
from .models import User
|
||||
|
||||
|
||||
@shared_task()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from django.urls import path
|
||||
|
||||
from {{ cookiecutter.project_slug }}.users.views import user_detail_view
|
||||
from {{ cookiecutter.project_slug }}.users.views import user_redirect_view
|
||||
from {{ cookiecutter.project_slug }}.users.views import user_update_view
|
||||
from .views import user_detail_view
|
||||
from .views import user_redirect_view
|
||||
from .views import user_update_view
|
||||
|
||||
app_name = "users"
|
||||
urlpatterns = [
|
||||
|
|
Loading…
Reference in New Issue
Block a user