Merge branch 'master' into yotamtal-master

# Conflicts:
#	CONTRIBUTORS.rst
This commit is contained in:
Bruno Alla 2020-12-10 18:59:14 +00:00
commit 6573e63908
78 changed files with 4066 additions and 787 deletions

56
.github/CONTRIBUTORS-template.md vendored Normal file
View File

@ -0,0 +1,56 @@
# Contributors
## Core Developers
These contributors have commit flags for the repository, and are able to
accept and merge pull requests.
<table>
<tr>
<th>Name</th>
<th>Github</th>
<th>Twitter</th>
</tr>
{%- for contributor in core_contributors %}
<tr>
<td>{{ contributor.name }}</td>
<td>
<a href="https://github.com/{{ contributor.github_login }}">{{ contributor.github_login }}</a>
</td>
<td>{{ contributor.twitter_username }}</td>
</tr>
{%- endfor %}
</table>
*Audrey is also the creator of Cookiecutter. Audrey and Daniel are on
the Cookiecutter core team.*
## Other Contributors
Listed in alphabetical order.
<table>
<tr>
<th>Name</th>
<th>Github</th>
<th>Twitter</th>
</tr>
{%- for contributor in other_contributors %}
<tr>
<td>{{ contributor.name }}</td>
<td>
<a href="https://github.com/{{ contributor.github_login }}">{{ contributor.github_login }}</a>
</td>
<td>{{ contributor.twitter_username }}</td>
</tr>
{%- endfor %}
</table>
### Special Thanks
The following haven't provided code directly, but have provided
guidance and advice.
- Jannis Leidel
- Nate Aune
- Barry Morrison

4
.github/FUNDING.yml vendored
View File

@ -1,7 +1,7 @@
# These are supported funding model platforms
github: pydanny
patreon: roygreenfeld
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

View File

@ -1 +0,0 @@
## [Make sure to follow one of the issue templates we've got](https://github.com/pydanny/cookiecutter-django/issues/new/choose), otherwise the issue might be closed immeditely

View File

@ -1,21 +1,32 @@
---
name: Bug Report
about: Report a bug
labels: bug
---
## What happened?
## What should've happened instead?
## Additional details
<!-- To assist you best, please include commands that you've run, options you've selected and any relevant logs -->
## Steps to reproduce
[//]: # (Any or all of the following:)
[//]: # (* Host system configuration: OS, Docker & friends' versions etc.)
[//]: # (* Replay file https://cookiecutter.readthedocs.io/en/latest/advanced/replay.html)
[//]: # (* Logs)
* Host system configuration:
* Version of cookiecutter CLI (get it with `cookiecutter --version`):
* OS:
* Python version:
* Docker versions (if using Docker):
* ...
* Options selected and/or [replay file](https://cookiecutter.readthedocs.io/en/latest/advanced/replay.html):
```
```
<summary>
Logs:
<details>
<pre>
$ cookiecutter https://github.com/pydanny/cookiecutter-django
project_name [Project Name]: ...
</pre>
</details>
</summary>

View File

@ -1,24 +1,13 @@
---
name: New Feature Proposal
about: Propose a new feature
labels: enhancement
---
## Description
[//]: # (What's it you're proposing? How should it be implemented?)
What are you proposing? How should it be implemented?
## Rationale
[//]: # (Why should this feature be implemented?)
## Use case(s) / visualization(s)
[//]: # ("Better to see something once than to hear about it a thousand times.")
Why should this feature be implemented?

View File

@ -1,24 +0,0 @@
---
name: Improvement Suggestion
about: Let us know how we could improve
---
## Description
[//]: # (What's it you're proposing? How should it be implemented?)
## Rationale
[//]: # (Why should this feature be implemented?)
## Use case(s) / visualization(s)
[//]: # ("Better to see something once than to hear about it a thousand times.")

View File

@ -3,8 +3,10 @@ name: Paid Support Request
about: Ask Core Team members to help you out
---
Provided your question goes beyound [regular support](https://github.com/pydanny/cookiecutter-django/issues/new?template=question.md), and/or the task at hand is of timely/high priority nature use the below information to reach out for contributors directly.
Provided your question goes beyond [regular support](https://github.com/pydanny/cookiecutter-django/issues/new?template=question.md), and/or the task at hand is of timely/high priority nature use the below information to reach out for contributors directly.
* Daniel Roy Greenfeld, Project Lead ([GitHub](https://github.com/pydanny), [Patreon](https://www.patreon.com/danielroygreenfeld)): expertise in Django and AWS ELB.
* Nikita Shupeyko, Core Developer ([GitHub](https://github.com/webyneter)): expertise in Python/Django, hands-on DevOps and frontend experience.
* Bruno Alla, Core Developer ([GitHub](https://github.com/sponsors/browniebroke)).

View File

@ -1,6 +1,11 @@
---
name: Question
about: Please, ask your question on StackOverflow or Gitter
about: Please consider asking your question on StackOverflow or Slack
labels: question
---
First, make sure to examine [the docs](https://cookiecutter-django.readthedocs.io/en/latest/). If that doesn't help post a question on [StackOverflow](https://stackoverflow.com/questions/tagged/cookiecutter-django) tagged with `cookiecutter-django`. Finally, feel free to join [Gitter](https://gitter.im/pydanny/cookiecutter-django) and ask around.
First, make sure to examine [the docs](https://cookiecutter-django.readthedocs.io/en/latest/).
If that doesn't help, post a question on [StackOverflow](https://stackoverflow.com/questions/tagged/cookiecutter-django) tagged with `cookiecutter-django`, you might get more visibility there than on our issue tracker.
Finally, feel free to join [Slack](https://join.slack.com/t/cookie-cutter/shared_invite/enQtNzI0Mzg5NjE5Nzk5LTRlYWI2YTZhYmQ4YmU1Y2Q2NmE1ZjkwOGM0NDQyNTIwY2M4ZTgyNDVkNjMxMDdhZGI5ZGE5YmJjM2M3ODJlY2U) and ask around.

View File

@ -1,28 +0,0 @@
---
name: Regression Report
about: Let us know if something that'd been working has broke
---
## What happened before?
## What happens now?
## Last stable commit / Since when?
## Steps to reproduce
[//]: # (Any or all of the following:)
[//]: # (* Host system configuration: OS, Docker & friends' versions etc.)
[//]: # (* Project generation options)
[//]: # (* Logs)

View File

@ -1,27 +1,18 @@
[//]: # (Thank you for helping us out: your efforts mean great deal to the project and the community as a whole!)
[//]: # (Before you proceed:)
[//]: # (1. Make sure to add yourself to `CONTRIBUTORS.rst` through this PR provided you're contributing here for the first time)
[//]: # (2. Don't forget to update the `docs/` presuming others would benefit from a concise description of whatever that you're proposing)
<!-- Thank you for helping us out: your efforts mean a great deal to the project and the community as a whole! -->
## Description
[//]: # (What's it you're proposing?)
<!-- What's it you're proposing? -->
Checklist:
- [ ] I've made sure that `tests/test_cookiecutter_generation.py` is updated accordingly (especially if adding or updating a template option)
- [ ] I've updated the documentation or confirm that my change doesn't require any updates
## Rationale
[//]: # (Why does the project need that?)
## Use case(s) / visualization(s)
[//]: # ("Better to see something once than to hear about it a thousand times.")
<!--
Why does this project need the change you're proposing?
If this pull request fixes an open issue, don't forget to link it with `Fix #NNNN`
-->

9
.github/changelog-template.md vendored Normal file
View File

@ -0,0 +1,9 @@
## [{{merge_date.strftime('%Y-%m-%d')}}]
{%- for change_type, pulls in grouped_pulls.items() %}
{%- if pulls %}
### {{ change_type }}
{%- for pull_request in pulls %}
- {{ pull_request.title }} ([#{{ pull_request.number }}]({{ pull_request.url }}))
{%- endfor -%}
{% endif -%}
{% endfor -%}

1056
.github/contributors.json vendored Normal file

File diff suppressed because it is too large Load Diff

10
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,10 @@
# Config for Dependabot updates. See Documentation here:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
# Update Github actions in workflows
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"

85
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,85 @@
name: CI
on:
push:
branches: [ master ]
pull_request:
jobs:
tox:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
tox-env:
- py38
- black-template
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install dependencies
run: |
python -m pip install -U pip
python -m pip install -U tox
- name: Tox ${{ matrix.tox-env }}
run: tox -e ${{ matrix.tox-env }}
docker:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
script:
- name: Basic
args: ""
- name: Extended
args: "use_celery=y use_drf=y js_task_runner=Gulp"
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Docker ${{ matrix.script.name }}
run: sh tests/test_docker.sh ${{ matrix.script.args }}
bare:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
script:
- name: With Celery
args: "use_celery=y use_compressor=y"
services:
redis:
image: redis:5.0
ports:
- 6379:6379
postgres:
image: postgres:12
ports:
- 5432:5432
env:
POSTGRES_PASSWORD: postgres
env:
CELERY_BROKER_URL: "redis://localhost:6379/0"
# postgres://user:password@host:port/database
DATABASE_URL: "postgres://postgres:postgres@localhost:5432/postgres"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Bare Metal ${{ matrix.script.name }}
run: sh tests/test_bare.sh ${{ matrix.script.args }}

62
.github/workflows/issue-manager.yml vendored Normal file
View File

@ -0,0 +1,62 @@
# Automatically close issues that have a keyword mark (an HTML comment)
# in the last comment in the issue, by a group of predefined users, after a custom delay.
# https://github.com/tiangolo/issue-manager
# Default config:
# <!-- issue-manager: answered -->
# Wait 10 days and comment: "Assuming the original issue was solved, it will be automatically closed now"
# Extra config:
# '<!-- issue-manager: waiting -->'
# Wait 10 days and comment: "Automatically closing. To re-open, please provide the additional information requested"
name: Issue Manager
on:
# Every day at midnight
schedule:
- cron: "0 0 * * *"
# Manual trigger
workflow_dispatch:
jobs:
issue-manager:
runs-on: ubuntu-latest
steps:
- uses: tiangolo/issue-manager@0.3.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
config: >
{
"answered": {
"delay": 864000,
"message": "Assuming the original issue was solved, it will be automatically closed now.",
"users": [
"pydanny",
"audreyr",
"luzfcb",
"theskumar",
"jayfk",
"burhan",
"webyneter",
"browniebroke",
"sfdye"
]
},
"waiting": {
"delay": 864000,
"message": "Automatically closing. To re-open, please provide the additional information requested.",
"users": [
"pydanny",
"audreyr",
"luzfcb",
"theskumar",
"jayfk",
"burhan",
"webyneter",
"browniebroke",
"sfdye"
]
}
}

View File

@ -0,0 +1,36 @@
# Run pre-commit autoupdate every day at midnight
# and create a pull request if any changes
name: Pre-commit auto-update
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch: # to trigger manually
jobs:
auto-update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install pre-commit
run: pip install pre-commit
- name: Run pre-commit autoupdate
working-directory: "{{cookiecutter.project_slug}}"
run: pre-commit autoupdate
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3.5.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: update/pre-commit-autoupdate
title: Auto-update pre-commit hooks
commit-message: Auto-update pre-commit hooks
body: Update versions of tools in pre-commit configs to latest version
labels: update

34
.github/workflows/update-changelog.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: Update Changelog
on:
# Every day at 2am
schedule:
- cron: "0 2 * * *"
# Manual trigger
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Update list
run: python scripts/update_changelog.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v4.7.2
with:
commit_message: Update Changelog
file_pattern: CHANGELOG.md

View File

@ -0,0 +1,30 @@
name: Update Contributors
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Update list
run: python scripts/update_contributors.py
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v4.7.2
with:
commit_message: Update Contributors
file_pattern: CONTRIBUTORS.md .github/contributors.json

12
.gitignore vendored
View File

@ -208,18 +208,6 @@ Session.vim
tags
### VirtualEnv template
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
[Bb]in
[Ii]nclude
[Ll]ib
[Ll]ib64
[Ss]cripts
pyvenv.cfg
pip-selfcheck.json
# Even though the project might be opened and edited
# in any of the JetBrains IDEs, it makes no sence whatsoever
# to 'run' anything within it since any particular cookiecutter

View File

@ -1,36 +0,0 @@
services:
- docker
language: python
python: 3.8
before_install:
- docker-compose -v
- docker -v
matrix:
include:
- name: Test results
script: tox -e py38
- name: Black template
script: tox -e black-template
- name: Basic Docker
script: sh tests/test_docker.sh
- name: Extended Docker
script: sh tests/test_docker.sh use_celery=y use_drf=y
- name: Bare metal
script: sh tests/test_bare.sh use_celery=y use_compressor=y
services:
- postgresql
- redis-server
env:
- CELERY_BROKER_URL=redis://localhost:6379/0
install:
- pip install tox
notifications:
email:
on_success: change
on_failure: always

View File

@ -1,6 +1,262 @@
# Change Log
All enhancements and patches to Cookiecutter Django will be documented in this file.
<!-- GENERATOR_PLACEHOLDER -->
## [2020-12-09]
### Changed
- Bump peter-evans/create-pull-request from v3.5.1 to v3.5.2 ([#2964](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2964))
## [2020-12-08]
### Updated
- Update pre-commit to 2.9.3 ([#2961](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2961))
## [2020-12-04]
### Updated
- Update django-debug-toolbar to 3.2 ([#2959](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2959))
## [2020-12-02]
### Updated
- Update django-model-utils to 4.1.1 ([#2957](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2957))
- Update pygithub to 1.54 ([#2958](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2958))
## [2020-11-26]
### Updated
- Update django-extensions to 3.1.0 ([#2947](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2947))
- Update pre-commit to 2.9.2 ([#2948](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2948))
- Update django-allauth to 0.44.0 ([#2945](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2945))
## [2020-11-25]
### Changed
- Bump peter-evans/create-pull-request from v3.5.0 to v3.5.1 ([#2944](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2944))
## [2020-11-23]
### Updated
- Update uvicorn to 0.12.3 ([#2943](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2943))
- Update pre-commit to 2.9.0 ([#2942](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2942))
## [2020-11-21]
### Changed
- Fix after uvicorn 0.12.0 - Ship extra dependencies ([#2939](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2939))
## [2020-11-20]
### Updated
- Update sentry-sdk to 0.19.4 ([#2938](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2938))
## [2020-11-19]
### Updated
- Update django-crispy-forms to 1.10.0 ([#2937](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2937))
## [2020-11-17]
### Changed
- Bump peter-evans/create-pull-request from v2 to v3.5.0 ([#2936](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2936))
## [2020-11-15]
### Changed
- Fix formatting in docs ([#2935](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2935))
## [2020-11-13]
### Changed
- Upgrade factory-boy to 3.1.0 ([#2932](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2932))
### Updated
- Update sentry-sdk to 0.19.3 ([#2933](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2933))
- Update sphinx to 3.3.1 ([#2934](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2934))
## [2020-11-12]
### Changed
- Migrate CI to Github Actions ([#2931](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2931))
## [2020-11-06]
### Updated
- Update djangorestframework to 3.12.2 ([#2930](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2930))
## [2020-11-04]
### Changed
- Fix docs service and add RTD support ([#2920](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2920))
- Bump stefanzweifel/git-auto-commit-action from v4.6.0 to v4.7.2 ([#2914](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2914))
### Updated
- Auto-update pre-commit hooks ([#2908](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2908))
- Update mypy to 0.790 ([#2886](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2886))
- Update django-stubs to 1.7.0 ([#2916](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2916))
## [2020-11-03]
### Updated
- Update sentry-sdk to 0.19.2 ([#2926](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2926))
- Update sphinx to 3.3.0 ([#2925](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2925))
- Update django to 3.0.11 ([#2924](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2924))
- Update pytz to 2020.4 ([#2923](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2923))
- Update pre-commit to 2.8.2 ([#2919](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2919))
- Update pytest to 6.1.2 ([#2917](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2917))
- Update sh to 1.14.1 ([#2912](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2912))
- Update pytest-django to 4.1.0 ([#2911](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2911))
- Update pillow to 8.0.1 ([#2910](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2910))
- Update django-celery-beat to 2.1.0 ([#2907](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2907))
- Update uvicorn to 0.12.2 ([#2906](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2906))
## [2020-10-19]
### Updated
- Update sentry-sdk to 0.19.1 ([#2905](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2905))
## [2020-10-17]
### Updated
- Update django-allauth to 0.43.0 ([#2901](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2901))
- Update pytest-django to 4.0.0 ([#2903](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2903))
## [2020-10-15]
### Updated
- Update pillow to 8.0.0 ([#2898](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2898))
## [2020-10-14]
### Updated
- Auto-update pre-commit hooks ([#2897](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2897))
- Update sentry-sdk to 0.19.0 ([#2896](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2896))
## [2020-10-13]
### Updated
- Update isort to 5.6.4 ([#2895](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2895))
## [2020-10-12]
### Changed
- Bump stefanzweifel/git-auto-commit-action from v4.5.1 to v4.6.0 ([#2893](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2893))
### Updated
- Auto-update pre-commit hooks ([#2892](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2892))
## [2020-10-11]
### Updated
- Auto-update pre-commit hooks ([#2890](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2890))
- Update isort to 5.6.3 ([#2891](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2891))
- Update django-anymail to 8.1 ([#2887](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2887))
- Update tox to 3.20.1 ([#2885](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2885))
## [2020-10-09]
### Updated
- Auto-update pre-commit hooks ([#2884](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2884))
- Update isort to 5.6.1 ([#2883](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2883))
## [2020-10-08]
### Changed
- Add dedicated websockets package ([#2881](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2881))
### Updated
- Update isort to 5.6.0 ([#2882](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2882))
## [2020-10-04]
### Updated
- Update pytest to 6.1.1 ([#2880](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2880))
- Update mypy and django-stubs ([#2874](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2874))
- Auto-update pre-commit hooks ([#2876](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2876))
- Update flake8 to 3.8.4 ([#2877](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2877))
## [2020-10-01]
### Changed
- Bump actions/setup-python from v2.1.2 to v2.1.3 ([#2869](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2869))
### Updated
- Update ipdb to 0.13.4 ([#2873](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2873))
- Auto-update pre-commit hooks ([#2867](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2867))
- Update uvicorn to 0.12.1 ([#2866](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2866))
- Update isort to 5.5.4 ([#2864](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2864))
- Update sentry-sdk to 0.18.0 ([#2863](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2863))
- Update djangorestframework to 3.12.1 ([#2862](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2862))
- Update pytest to 6.1.0 ([#2859](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2859))
- Update django-debug-toolbar to 3.1.1 ([#2855](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2855))
## [2020-09-23]
### Updated
- Update sentry-sdk to 0.17.7 ([#2847](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2847))
- Update django-debug-toolbar to 3.1 ([#2846](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2846))
## [2020-09-21]
### Changed
- Adding GitHub-Action CI Option ([#2837](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2837))
### Updated
- Update django-debug-toolbar to 3.0 ([#2842](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2842))
- Auto-update pre-commit hooks ([#2843](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2843))
- Update isort to 5.5.3 ([#2844](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2844))
## [2020-09-18]
### Updated
- Update django-extensions to 3.0.9 ([#2839](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2839))
## [2020-09-16]
### Updated
- Update sentry-sdk to 0.17.6 ([#2833](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2833))
- Update pytest-django to 3.10.0 ([#2832](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2832))
## [2020-09-14]
### Fixed
- Downgrade Celery to 4.4.6 ([#2829](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2829))
### Updated
- Update sentry-sdk to 0.17.5 ([#2828](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2828))
- Update coverage to 5.3 ([#2826](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2826))
- Update django-storages to 1.10.1 ([#2825](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2825))
## [2020-09-12]
### Updated
- Updating Traefik version from 2.0 to 2.2.11 ([#2814](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2814))
- Update pytest to 6.0.2 ([#2819](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2819))
- Update django-anymail to 8.0 ([#2818](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2818))
## [2020-09-11]
### Updated
- Auto-update pre-commit hooks ([#2809](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2809))
## [2020-09-10]
### Updated
- Update isort to 5.5.2 ([#2807](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2807))
- Update sentry-sdk to 0.17.4 ([#2805](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2805))
## [2020-09-09]
### Changed
- Update actions/setup-python requirement to v2.1.2 ([#2804](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2804))
- Clean up nested venv files from `.gitignore` ([#2800](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2800))
## [2020-09-08]
### Changed
- Traeffik and Django dockerfile changes ([#2801](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2801))
## [2020-09-07]
### Changed
- Add :z/:Z to mounted volumes in {local,production}.yml ([#2663](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2663))
- Remove --no-binary option for psycopg2 ([#2798](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2798))
- Updated Gitlab CI to use Python 3.8 instead of Python 3.7 ([#2794](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2794))
### Fixed
- Fix options for sphinx-autobuild in docs Makefile ([#2799](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2799))
### Updated
- Update psycopg2-binary to 2.8.6 ([#2797](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2797))
## [2020-09-05]
### Updated
- Auto-update pre-commit hooks ([#2793](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2793))
## [2020-09-04]
### Updated
- Update django-extensions to 3.0.8 ([#2792](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2792))
- Update isort to 5.5.1 ([#2791](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2791))
- Auto-update pre-commit hooks ([#2790](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2790))
- Update isort to 5.5.0 ([#2789](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2789))
## [2020-09-02]
### Changed
- Add environment and traces_sample_rate keyword to sentry_sdk.init ([#2777](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2777))
### Updated
- Update sentry-sdk to 0.17.3 ([#2788](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2788))
- Update django-extensions to 3.0.7 ([#2787](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2787))
## [2020-09-01]
### Changed
- Exclude venv directory and update document link ([#2780](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2780))
### Updated
- Update tox to 3.20.0 ([#2786](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2786))
- Update django-storages to 1.10 ([#2781](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2781))
- Update sentry-sdk to 0.17.2 ([#2784](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2784))
- Update django to 3.0.10 ([#2785](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2785))
- Update sphinx-autobuild to 2020.9.1 ([#2782](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2782))
- Update django-extensions to 3.0.6 ([#2783](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2783))
## [2020-08-31]
### Updated
- Update sh to 1.14.0 ([#2779](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2779))
- Update sentry-sdk to 0.17.1 ([#2778](https://api.github.com/repos/pydanny/cookiecutter-django/pulls/2778))
## [2020-04-13]
### Changed
- Updated to Python 3.8 (@codnee)

View File

@ -8,7 +8,6 @@ Getting your pull request merged in
#. Keep it small. The smaller the pull request the more likely I'll pull it in.
#. Pull requests that fix a current issue get priority for review.
#. If you're not already in the `CONTRIBUTORS.rst` file, add yourself!
Testing
-------

1501
CONTRIBUTORS.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,420 +0,0 @@
Contributors
============
Core Developers
---------------
These contributors have commit flags for the repository,
and are able to accept and merge pull requests.
=========================== ================= ===========
Name Github Twitter
=========================== ================= ===========
Daniel Roy Greenfeld `@pydanny`_ @pydanny
Audrey Roy Greenfeld* `@audreyr`_ @audreyr
Fábio C. Barrionuevo da Luz `@luzfcb`_ @luzfcb
Saurabh Kumar `@theskumar`_ @_theskumar
Jannis Gebauer `@jayfk`_
Burhan Khalid `@burhan`_ @burhan
Nikita Shupeyko `@webyneter`_ @webyneter
Bruno Alla               `@browniebroke`_ @_BrunoAlla
Wan Liuyang `@sfdye`_ @sfdye
=========================== ================= ===========
*Audrey is also the creator of Cookiecutter. Audrey and
Daniel are on the Cookiecutter core team.*
.. _@pydanny: https://github.com/pydanny
.. _@luzfcb: https://github.com/luzfcb
.. _@theskumar: https://github.com/theskumar
.. _@audreyr: https://github.com/audreyr
.. _@jayfk: https://github.com/jayfk
.. _@webyneter: https://github.com/webyneter
.. _@browniebroke: https://github.com/browniebroke
.. _@sfdye: https://github.com/sfdye
Other Contributors
------------------
Listed in alphabetical order.
========================== ============================ ==============
Name Github Twitter
========================== ============================ ==============
18 `@dezoito`_
2O4 `@2O4`_
a7p `@a7p`_
Aaron Eikenberry `@aeikenberry`_
Adam Bogdał `@bogdal`_
Adam Dobrawy `@ad-m`_
Adam Steele `@adammsteele`_
Agam Dua
Agustín Scaramuzza `@scaramagus`_ @scaramagus
Alberto Sanchez `@alb3rto`_
Alex Tsai `@caffodian`_
Alvaro [Andor] `@andor-pierdelacabeza`_
Amjith Ramanujam `@amjith`_
Andreas Meistad `@ameistad`_
Andres Gonzalez `@andresgz`_
Andrew Mikhnevich `@zcho`_
Andrew Chen Wang `@Andrew-Chen-Wang`_
Andy Rose
Anna Callahan `@jazztpt`_
Anna Sidwell `@takkaria`_
Antonia Blair `@antoniablair`_ @antoniablairart
Anuj Bansal `@ahhda`_
Arcuri Davide `@dadokkio`_
Areski Belaid `@areski`_
AsheKR `@ashekr`_
Ashley Camba
Barclay Gauld `@yunti`_
Bartek `@btknu`_
Ben Lopatin
Ben Warren `@bwarren2`_
Benjamin Abel
Bert de Miranda `@bertdemiranda`_
Bo Lopker `@blopker`_
Bo Peng `@BoPeng`_
Bouke Haarsma
Brent Payne `@brentpayne`_ @brentpayne
Bruce Olivier `@bolivierjr`_
Burhan Khalid            `@burhan`_                   @burhan
Caio Ariede `@caioariede`_ @caioariede
Carl Johnson `@carlmjohnson`_ @carlmjohnson
Catherine Devlin `@catherinedevlin`_
Cédric Gaspoz `@cgaspoz`_
Charlie Smith `@chuckus`_
Chris Curvey `@ccurvey`_
Chris Franklin
Chris Franklin `@hairychris`_
Chris Pappalardo `@ChrisPappalardo`_
Christopher Clarke `@chrisdev`_
Cole Mackenzie `@cmackenzie1`_
Cole Maclean `@cole`_ @cole
Collederas `@Collederas`_
Craig Margieson `@cmargieson`_
Cristian Vargas `@cdvv7788`_
Cullen Rhodes `@c-rhodes`_
Curtis St Pierre `@curtisstpierre`_ @cstpierre1388
Dan Shultz `@shultz`_
Dani Hodovic `@danihodovic`_
Daniel Hepper `@dhepper`_ @danielhepper
Daniel Hillier `@danifus`_
Daniel Sears `@highpost`_ @highpost
Daniele Tricoli `@eriol`_
David Díaz `@ddiazpinto`_ @DavidDiazPinto
Davit Tovmasyan `@davitovmasyan`_
Davur Clementsen `@dsclementsen`_ @davur
Delio Castillo `@jangeador`_ @jangeador
Demetris Stavrou `@demestav`_
Denis Bobrov `@delneg`_
Denis Orehovsky `@apirobot`_
Denis Savran `@blaxpy`_
Diane Chen `@purplediane`_ @purplediane88
Dónal Adams `@epileptic-fish`_
Dong Huynh `@trungdong`_
Duda Nogueira `@dudanogueira`_ @dudanogueira
Emanuel Calso `@bloodpet`_ @bloodpet
Eraldo Energy `@eraldo`_
Eric Groom `@ericgroom`_
Ernesto Cedeno `@codnee`_
Eyad Al Sibai `@eyadsibai`_
Felipe Arruda `@arruda`_
Florian Idelberger `@step21`_ @windrush
Gabriel Mejia `@elgartoinf`_ @elgartoinf
Garry Cairns `@garry-cairns`_
Garry Polley `@garrypolley`_
Gilbishkosma `@Gilbishkosma`_
Glenn Wiskur `@gwiskur`_
Guilherme Guy `@guilherme1guy`_
Hamish Durkin `@durkode`_
Hana Quadara `@hanaquadara`_
Hannah Lazarus `@hanhanhan`_
Harry Moreno `@morenoh149`_ @morenoh149
Harry Percival `@hjwp`_
Hendrik Schneider `@hendrikschneider`_
Henrique G. G. Pereira `@ikkebr`_
Howie Zhao `@howiezhao`_
Ian Lee `@IanLee1521`_
Irfan Ahmad `@erfaan`_ @erfaan
Isaac12x `@Isaac12x`_
Ivan Khomutov `@ikhomutov`_
James Williams `@jameswilliams1`_
Jan Van Bruggen `@jvanbrug`_
Jelmer Draaijer `@foarsitter`_
Jerome Caisip `@jeromecaisip`_
Jens Nilsson `@phiberjenz`_
Jerome Leclanche `@jleclanche`_ @Adys
Jimmy Gitonga `@afrowave`_ @afrowave
John Cass `@jcass77`_ @cass_john
Jonathan Thompson `@nojanath`_
Jules Cheron `@jules-ch`_
Julien Almarcha `@sladinji`_
Julio Castillo `@juliocc`_
Kaido Kert `@kaidokert`_
kappataumu `@kappataumu`_ @kappataumu
Kaveh `@ka7eh`_
Keith Bailey `@keithjeb`_
Keith Webber `@townie`_
Kevin A. Stone
Kevin Ndung'u `@kevgathuku`_
Keyvan Mosharraf `@keyvanm`_
Krzysztof Szumny `@noisy`_
Krzysztof Żuraw `@krzysztofzuraw`_
Leo won `@leollon`_
Leo Zhou `@glasslion`_
Leon Kim `@PilhwanKim`_
Leonardo Jimenez `@xpostudio4`_
Lin Xianyi `@iynaix`_
Luis Nell `@originell`_
Lukas Klein
Lyla Fischer
Malik Sulaimanov `@flyudvik`_ @flyudvik
Martin Blech
Martin Saizar `@msaizar`_
Mateusz Ostaszewski `@mostaszewski`_
Mathijs Hoogland `@MathijsHoogland`_
Matt Braymer-Hayes `@mattayes`_ @mattayes
Matt Knapper `@mknapper1`_
Matt Linares
Matt Menzenski `@menzenski`_
Matt Warren `@mfwarren`_
Matthew Sisley `@mjsisley`_
Meghan Heintz `@dot2dotseurat`_
Mesut Yılmaz `@myilmaz`_
Michael Gecht `@mimischi`_ @_mischi
Michael Samoylov `@msamoylov`_
Min ho Kim `@minho42`_
mozillazg `@mozillazg`_
Nico Stefani `@nicolas471`_ @moby_dick91
Oleg Russkin `@rolep`_
Pablo `@oubiga`_
Parbhat Puri `@parbhat`_
Pawan Chaurasia `@rjsnh1522`_
Peter Bittner `@bittner`_
Peter Coles `@mrcoles`_
Philipp Matthies `@canonnervio`_
Pierre Chiquet `@pchiquet`_
Raony Guimarães Corrêa `@raonyguimaraes`_
Raphael Pierzina `@hackebrot`_
Reggie Riser `@reggieriser`_
René Muhl `@rm--`_
Roman Afanaskin `@siauPatrick`_
Roman Osipenko `@romanosipenko`_
Russell Davies
Sam Collins `@MightySCollins`_
Sascha `@saschalalala`_ @saschalalala
Shupeyko Nikita `@webyneter`_
Sławek Ehlert `@slafs`_
Sorasful `@sorasful`_
Srinivas Nyayapati `@shireenrao`_
stepmr `@stepmr`_
Steve Steiner `@ssteinerX`_
Sudarshan Wadkar `@wadkar`_
Sule Marshall `@suledev`_
Tano Abeleyra `@tanoabeleyra`_
Taylor Baldwin
Théo Segonds `@show0k`_
Tim Claessens `@timclaessens`_
Tim Freund `@timfreund`_
Tom Atkins `@knitatoms`_
Tom Offermann
Travis McNeill `@Travistock`_ @tavistock_esq
Tubo Shi `@Tubo`_
Umair Ashraf `@umrashrf`_ @fabumair
Vadim Iskuchekov `@Egregors`_ @egregors
Vicente G. Reyes `@reyesvicente`_ @highcenburg
Vitaly Babiy
Vivian Guillen `@viviangb`_
Vlad Doster `@vladdoster`_
Will Farley `@goldhand`_ @g01dhand
William Archinal `@archinal`_
Xaver Y.R. Chen `@yrchen`_ @yrchen
Yaroslav Halchenko
Yotam Tal `@yotamtal`_
Yuchen Xie `@mapx`_
========================== ============================ ==============
.. _@a7p: https://github.com/a7p
.. _@2O4: https://github.com/2O4
.. _@ad-m: https://github.com/ad-m
.. _@adammsteele: https://github.com/adammsteele
.. _@aeikenberry: https://github.com/aeikenberry
.. _@afrowave: https://github.com/afrowave
.. _@ahhda: https://github.com/ahhda
.. _@alb3rto: https://github.com/alb3rto
.. _@ameistad: https://github.com/ameistad
.. _@amjith: https://github.com/amjith
.. _@andor-pierdelacabeza: https://github.com/andor-pierdelacabeza
.. _@andresgz: https://github.com/andresgz
.. _@antoniablair: https://github.com/antoniablair
.. _@Andrew-Chen-Wang: https://github.com/Andrew-Chen-Wang
.. _@apirobot: https://github.com/apirobot
.. _@archinal: https://github.com/archinal
.. _@areski: https://github.com/areski
.. _@arruda: https://github.com/arruda
.. _@ashekr: https://github.com/ashekr
.. _@bertdemiranda: https://github.com/bertdemiranda
.. _@bittner: https://github.com/bittner
.. _@blaxpy: https://github.com/blaxpy
.. _@bloodpet: https://github.com/bloodpet
.. _@blopker: https://github.com/blopker
.. _@bogdal: https://github.com/bogdal
.. _@bolivierjr: https://github.com/bolivierjr
.. _@BoPeng: https://github.com/BoPeng
.. _@brentpayne: https://github.com/brentpayne
.. _@btknu: https://github.com/btknu
.. _@burhan: https://github.com/burhan
.. _@bwarren2: https://github.com/bwarren2
.. _@c-rhodes: https://github.com/c-rhodes
.. _@caffodian: https://github.com/caffodian
.. _@canonnervio: https://github.com/canonnervio
.. _@caioariede: https://github.com/caioariede
.. _@carlmjohnson: https://github.com/carlmjohnson
.. _@catherinedevlin: https://github.com/catherinedevlin
.. _@ccurvey: https://github.com/ccurvey
.. _@cdvv7788: https://github.com/cdvv7788
.. _@cgaspoz: https://github.com/cgaspoz
.. _@chrisdev: https://github.com/chrisdev
.. _@ChrisPappalardo: https://github.com/ChrisPappalardo
.. _@chuckus: https://github.com/chuckus
.. _@cmackenzie1: https://github.com/cmackenzie1
.. _@cmargieson: https://github.com/cmargieson
.. _@codnee: https://github.com/codnee
.. _@cole: https://github.com/cole
.. _@Collederas: https://github.com/Collederas
.. _@curtisstpierre: https://github.com/curtisstpierre
.. _@dadokkio: https://github.com/dadokkio
.. _@danihodovic: https://github.com/danihodovic
.. _@danifus: https://github.com/danifus
.. _@davitovmasyan: https://github.com/davitovmasyan
.. _@ddiazpinto: https://github.com/ddiazpinto
.. _@delneg: https://github.com/delneg
.. _@demestav: https://github.com/demestav
.. _@dezoito: https://github.com/dezoito
.. _@dhepper: https://github.com/dhepper
.. _@dot2dotseurat: https://github.com/dot2dotseurat
.. _@dudanogueira: https://github.com/dudanogueira
.. _@dsclementsen: https://github.com/dsclementsen
.. _@guilherme1guy: https://github.com/guilherme1guy
.. _@durkode: https://github.com/durkode
.. _@Egregors: https://github.com/Egregors
.. _@elgartoinf: https://gihub.com/elgartoinf
.. _@epileptic-fish: https://gihub.com/epileptic-fish
.. _@eraldo: https://github.com/eraldo
.. _@erfaan: https://github.com/erfaan
.. _@ericgroom: https://github.com/ericgroom
.. _@eriol: https://github.com/eriol
.. _@eyadsibai: https://github.com/eyadsibai
.. _@flyudvik: https://github.com/flyudvik
.. _@foarsitter: https://github.com/foarsitter
.. _@garry-cairns: https://github.com/garry-cairns
.. _@garrypolley: https://github.com/garrypolley
.. _@Gilbishkosma: https://github.com/Gilbishkosma
.. _@gwiskur: https://github.com/gwiskur
.. _@glasslion: https://github.com/glasslion
.. _@goldhand: https://github.com/goldhand
.. _@hackebrot: https://github.com/hackebrot
.. _@hairychris: https://github.com/hairychris
.. _@hanaquadara: https://github.com/hanaquadara
.. _@hanhanhan: https://github.com/hanhanhan
.. _@hendrikschneider: https://github.com/hendrikschneider
.. _@highpost: https://github.com/highpost
.. _@hjwp: https://github.com/hjwp
.. _@howiezhao: https://github.com/howiezhao
.. _@IanLee1521: https://github.com/IanLee1521
.. _@ikhomutov: https://github.com/ikhomutov
.. _@jameswilliams1: https://github.com/jameswilliams1
.. _@ikkebr: https://github.com/ikkebr
.. _@Isaac12x: https://github.com/Isaac12x
.. _@iynaix: https://github.com/iynaix
.. _@jangeador: https://github.com/jangeador
.. _@jazztpt: https://github.com/jazztpt
.. _@jcass77: https://github.com/jcass77
.. _@jeromecaisip: https://github.com/jeromecaisip
.. _@jleclanche: https://github.com/jleclanche
.. _@jules-ch: https://github.com/jules-ch
.. _@juliocc: https://github.com/juliocc
.. _@jvanbrug: https://github.com/jvanbrug
.. _@ka7eh: https://github.com/ka7eh
.. _@kaidokert: https://github.com/kaidokert
.. _@kappataumu: https://github.com/kappataumu
.. _@keithjeb: https://github.com/keithjeb
.. _@kevgathuku: https://github.com/kevgathuku
.. _@keyvanm: https://github.com/keyvanm
.. _@knitatoms: https://github.com/knitatoms
.. _@krzysztofzuraw: https://github.com/krzysztofzuraw
.. _@leollon: https://github.com/leollon
.. _@MathijsHoogland: https://github.com/MathijsHoogland
.. _@mapx: https://github.com/mapx
.. _@mattayes: https://github.com/mattayes
.. _@menzenski: https://github.com/menzenski
.. _@mfwarren: https://github.com/mfwarren
.. _@MightySCollins: https://github.com/MightySCollins
.. _@mimischi: https://github.com/mimischi
.. _@minho42: https://github.com/minho42
.. _@mjsisley: https://github.com/mjsisley
.. _@mknapper1: https://github.com/mknapper1
.. _@morenoh149: https://github.com/morenoh149
.. _@mostaszewski: https://github.com/mostaszewski
.. _@mozillazg: https://github.com/mozillazg
.. _@mrcoles: https://github.com/mrcoles
.. _@msaizar: https://github.com/msaizar
.. _@msamoylov: https://github.com/msamoylov
.. _@myilmaz: https://github.com/myilmaz
.. _@nicolas471: https://github.com/nicolas471
.. _@noisy: https://github.com/noisy
.. _@nojanath: https://github.com/nojanath
.. _@originell: https://github.com/originell
.. _@oubiga: https://github.com/oubiga
.. _@parbhat: https://github.com/parbhat
.. _@rjsnh1522: https://github.com/rjsnh1522
.. _@pchiquet: https://github.com/pchiquet
.. _@phiberjenz: https://github.com/phiberjenz
.. _@PilhwanKim: https://github.com/PilhwanKim
.. _@purplediane: https://github.com/purplediane
.. _@raonyguimaraes: https://github.com/raonyguimaraes
.. _@reggieriser: https://github.com/reggieriser
.. _@reyesvicente: https://github.com/reyesvicente
.. _@rm--: https://github.com/rm--
.. _@rolep: https://github.com/rolep
.. _@romanosipenko: https://github.com/romanosipenko
.. _@saschalalala: https://github.com/saschalalala
.. _@scaramagus: https://github.com/scaramagus
.. _@shireenrao: https://github.com/shireenrao
.. _@show0k: https://github.com/show0k
.. _@shultz: https://github.com/shultz
.. _@siauPatrick: https://github.com/siauPatrick
.. _@sladinji: https://github.com/sladinji
.. _@slafs: https://github.com/slafs
.. _@sorasful:: https://github.com/sorasful
.. _@ssteinerX: https://github.com/ssteinerx
.. _@step21: https://github.com/step21
.. _@stepmr: https://github.com/stepmr
.. _@suledev: https://github.com/suledev
.. _@takkaria: https://github.com/takkaria
.. _@tanoabeleyra: https://github.com/tanoabeleyra
.. _@timclaessens: https://github.com/timclaessens
.. _@timfreund: https://github.com/timfreund
.. _@townie: https://github.com/townie
.. _@Travistock: https://github.com/Tavistock
.. _@trungdong: https://github.com/trungdong
.. _@Tubo: https://github.com/tubo
.. _@umrashrf: https://github.com/umrashrf
.. _@viviangb: https://github.com/viviangb
.. _@vladdoster: https://github.com/vladdoster
.. _@wadkar: https://github.com/wadkar
.. _@xpostudio4: https://github.com/xpostudio4
.. _@yrchen: https://github.com/yrchen
.. _@yotamtal: https://github.com/yotamtal
.. _@yunti: https://github.com/yunti
.. _@zcho: https://github.com/zcho
Special Thanks
~~~~~~~~~~~~~~
The following haven't provided code directly, but have provided guidance and advice.
* Jannis Leidel
* Nate Aune
* Barry Morrison

View File

@ -1,8 +1,8 @@
Cookiecutter Django
=======================
===================
.. image:: https://travis-ci.org/pydanny/cookiecutter-django.svg?branch=master
:target: https://travis-ci.org/pydanny/cookiecutter-django?branch=master
.. image:: https://img.shields.io/github/workflow/status/pydanny/cookiecutter-django/CI/master
:target: https://github.com/pydanny/cookiecutter-django/actions?query=workflow%3ACI
:alt: Build Status
.. image:: https://readthedocs.org/projects/cookiecutter-django/badge/?version=latest
@ -96,7 +96,7 @@ Constraints
-----------
* Only maintained 3rd party libraries are used.
* Uses PostgreSQL everywhere (9.4 - 11.3)
* Uses PostgreSQL everywhere (9.4 - 12.3)
* Environment variables for configuration (This won't work with Apache/mod_wsgi).
Support this Project!
@ -110,16 +110,17 @@ This project is run by volunteers. Please support them in their efforts to maint
Projects that provide financial support to the maintainers:
Django Crash Course
~~~~~~~~~~~~~~~~~~~~~~~~~
.. image:: https://cdn.shopify.com/s/files/1/0304/6901/files/Django-Crash-Course-300x436.jpg
:name: Django Crash Course: Covers Django 3.0 and Python 3.8
.. image:: https://cdn.shopify.com/s/files/1/0304/6901/products/Two-Scoops-of-Django-3-Alpha-Cover_540x_26507b15-e489-470b-8a97-02773dd498d1_1080x.jpg
:name: Two Scoops of Django 3.x
:align: center
:alt: Django Crash Course
:target: https://www.roygreenfeld.com/products/django-crash-course
:alt: Two Scoops of Django
:target: https://www.feldroy.com/products//two-scoops-of-django-3-x
Django Crash Course for Django 3.0 and Python 3.8 is the best cheese-themed Django reference in the universe!
Two Scoops of Django 3.x is the best ice cream-themed Django reference in the universe!
pyup
~~~~~~~~~~~~~~~~~~
@ -176,11 +177,11 @@ Answer the prompts with your own desired options_. For example::
use_heroku [n]: y
use_compressor [n]: y
Select postgresql_version:
1 - 11.3
2 - 10.8
3 - 9.6
4 - 9.5
5 - 9.4
1 - 12.3
2 - 11.8
3 - 10.8
4 - 9.6
5 - 9.5
Choose from 1, 2, 3, 4, 5 [1]: 1
Select js_task_runner:
1 - None

View File

@ -18,11 +18,11 @@
"use_pycharm": "n",
"use_docker": "n",
"postgresql_version": [
"11.3",
"12.3",
"11.8",
"10.8",
"9.6",
"9.5",
"9.4"
"9.5"
],
"js_task_runner": [
"None",
@ -56,9 +56,9 @@
"ci_tool": [
"None",
"Travis",
"Gitlab"
"Gitlab",
"Github"
],
"keep_local_envs_in_vcs": "y",
"debug": "n"
}

View File

@ -82,7 +82,7 @@ The Traefik reverse proxy used in the default configuration will get you a valid
You can read more about this feature and how to configure it, at `Automatic HTTPS`_ in the Traefik docs.
.. _Automatic HTTPS: https://docs.traefik.io/configuration/acme/
.. _Automatic HTTPS: https://docs.traefik.io/https/acme/
(Optional) Postgres Data Volume Modifications

View File

@ -116,7 +116,7 @@ Consider the aforementioned ``.envs/.local/.postgres``: ::
The three envs we are presented with here are ``POSTGRES_DB``, ``POSTGRES_USER``, and ``POSTGRES_PASSWORD`` (by the way, their values have also been generated for you). You might have figured out already where these definitions will end up; it's all the same with ``django`` service container envs.
One final touch: should you ever need to merge ``.envs/production/*`` in a single ``.env`` run the ``merge_production_dotenvs_in_dotenv.py``: ::
One final touch: should you ever need to merge ``.envs/.production/*`` in a single ``.env`` run the ``merge_production_dotenvs_in_dotenv.py``: ::
$ python merge_production_dotenvs_in_dotenv.py
@ -178,8 +178,7 @@ When developing locally you can go with MailHog_ for email testing provided ``us
Celery tasks in local development
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When not using docker Celery tasks are set to run in Eager mode, so that a full stack is not needed. When using docker the task
scheduler will be used by default.
When not using docker Celery tasks are set to run in Eager mode, so that a full stack is not needed. When using docker the task scheduler will be used by default.
If you need tasks to be executed on the main thread during development set CELERY_TASK_ALWAYS_EAGER = True in config/settings/local.py.
@ -200,3 +199,96 @@ Prerequisites:
By default, it's enabled both in local and production environments (``local.yml`` and ``production.yml`` Docker Compose configs, respectively) through a ``flower`` service. For added security, ``flower`` requires its clients to provide authentication credentials specified as the corresponding environments' ``.envs/.local/.django`` and ``.envs/.production/.django`` ``CELERY_FLOWER_USER`` and ``CELERY_FLOWER_PASSWORD`` environment variables. Check out ``localhost:5555`` and see for yourself.
.. _`Flower`: https://github.com/mher/flower
Developing locally with HTTPS
-----------------------------
Increasingly it is becoming necessary to develop software in a secure environment in order that there are very few changes when deploying to production. Recently Facebook changed their policies for apps/sites that use Facebook login which requires the use of an HTTPS URL for the OAuth redirect URL. So if you want to use the ``users`` application with a OAuth provider such as Facebook, securing your communication to the local development environment will be necessary.
On order to create a secure environment, we need to have a trusted SSL certficate installed in our Docker application.
#. **Let's Encrypt**
The official line from Lets Encrypt is:
[For local development section] ... The best option: Generate your own certificate, either self-signed or signed by a local root, and trust it in your operating systems trust store. Then use that certificate in your local web server. See below for details.
See `letsencrypt.org - certificates-for-localhost`_
.. _`letsencrypt.org - certificates-for-localhost`: https://letsencrypt.org/docs/certificates-for-localhost/
#. **mkcert: Valid Https Certificates For Localhost**
`mkcert`_ is a simple by design tool that hides all the arcane knowledge required to generate valid TLS certificates. It works for any hostname or IP, including localhost. It supports macOS, Linux, and Windows, and Firefox, Chrome and Java. It even works on mobile devices with a couple manual steps.
See https://blog.filippo.io/mkcert-valid-https-certificates-for-localhost/
.. _`mkcert`: https://github.com/FiloSottile/mkcert/blob/master/README.md#supported-root-stores
After installing a trusted TLS certificate, configure your docker installation. We are going to configure an ``nginx`` reverse-proxy server. This makes sure that it does not interfere with our ``traefik`` configuration that is reserved for production environements.
These are the places that you should configure to secure your local environment.
certs
~~~~~
Take the certificates that you generated and place them in a folder called ``certs`` on the projects root folder. Assuming that you registered your local hostname as ``my-dev-env.local``, the certificates you will put in the folder should have the names ``my-dev-env.local.crt`` and ``my-dev-env.local.key``.
local.yml
~~~~~~~~~
#. Add the ``nginx-proxy`` service. ::
...
nginx-proxy:
image: jwilder/nginx-proxy:alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs
restart: always
depends_on:
- django
...
#. Link the ``nginx-proxy`` to ``django`` through environmental variables.
``django`` already has an ``.env`` file connected to it. Add the following variables. You should do this especially if you are working with a team and you want to keep your local environment details to yourself.
::
# HTTPS
# ------------------------------------------------------------------------------
VIRTUAL_HOST=my-dev-env.local
VIRTUAL_PORT=8000
The services run behind the reverse proxy.
config/settings/local.py
~~~~~~~~~~~~~~~~~~~~~~~~
You should allow the new hostname. ::
ALLOWED_HOSTS = ["localhost", "0.0.0.0", "127.0.0.1", "my-dev-env.local"]
Rebuild your ``docker`` application. ::
$ docker-compose -f local.yml up -d --build
Go to your browser and type in your URL bar ``https://my-dev-env.local``
See `https with nginx`_ for more information on this configuration.
.. _`https with nginx`: https://codewithhugo.com/docker-compose-local-https/
.gitignore
~~~~~~~~~~
Add ``certs/*`` to the ``.gitignore`` file. This allows the folder to be included in the repo but its contents to be ignored.
*This configuration is for local development environments only. Do not use this for production since you might expose your local* ``rootCA-key.pem``.

View File

@ -24,9 +24,9 @@ First things first.
$ source <virtual env path>/bin/activate
#. Install cookiecutter-django
#. Install cookiecutter-django: ::
$ cookiecutter gh:pydanny/cookiecutter-django ::
$ cookiecutter gh:pydanny/cookiecutter-django
#. Install development requirements: ::
@ -34,10 +34,10 @@ First things first.
$ git init # A git repo is required for pre-commit to install
$ pre-commit install
.. note::
.. note::
the `pre-commit` exists in the generated project as default.
for the details of `pre-commit`, follow the [site of pre-commit](https://pre-commit.com/).
the `pre-commit` exists in the generated project as default.
for the details of `pre-commit`, follow the [site of pre-commit](https://pre-commit.com/).
#. Create a new PostgreSQL database using createdb_: ::

View File

@ -4,42 +4,41 @@ Document
=========
This project uses Sphinx_ documentation generator.
After you have set up to `develop locally`_, run the following commands to generate the HTML documentation: ::
$ sphinx-build docs/ docs/_build/html/
After you have set up to `develop locally`_, run the following command from the project directory to build and serve HTML documentation: ::
$ make -C docs livehtml
If you set up your project to `develop locally with docker`_, run the following command: ::
$ docker-compose -f local.yml run --rm django sphinx-build docs/ docs/_build/html/
$ docker-compose -f local.yml up docs
Navigate to port 7000 on your host to see the documentation. This will be opened automatically at `localhost`_ for local, non-docker development.
Note: using Docker for documentation sets up a temporary SQLite file by setting the environment variable ``DATABASE_URL=sqlite:///readthedocs.db`` in ``docs/conf.py`` to avoid a dependency on PostgreSQL.
Generate API documentation
----------------------------
Sphinx can automatically generate documentation from docstrings, to enable this feature, follow these steps:
Edit the ``docs`` files and project application docstrings to create your documentation.
1. Add Sphinx extension in ``docs/conf.py`` file, like below: ::
Sphinx can automatically include class and function signatures and docstrings in generated documentation.
See the generated project documentation for more examples.
extensions = [
'sphinx.ext.autodoc',
]
Setting up ReadTheDocs
----------------------
2. Uncomment the following lines in the ``docs/conf.py`` file: ::
To setup your documentation on `ReadTheDocs`_, you must
# import django
# sys.path.insert(0, os.path.abspath('..'))
# os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
# django.setup()
1. Go to `ReadTheDocs`_ and login/create an account
2. Add your GitHub repository
3. Trigger a build
3. Run the following command: ::
$ sphinx-apidoc -f -o ./docs/modules/ ./tpub/ migrations/*
If you set up your project to `develop locally with docker`_, run the following command: ::
$ docker-compose -f local.yml run --rm django sphinx-apidoc -f -o ./docs/modules ./tpub/ migrations/*
4. Regenerate HTML documentation as written above.
Additionally, you can auto-build Pull Request previews, but `you must enable it`_.
.. _localhost: http://localhost:7000/
.. _Sphinx: https://www.sphinx-doc.org/en/master/index.html
.. _develop locally: ./developing-locally.html
.. _develop locally with docker: ./developing-locally-docker.html
.. _ReadTheDocs: https://readthedocs.org/
.. _you must enable it: https://docs.readthedocs.io/en/latest/guides/autobuild-docs-for-pull-requests.html#autobuild-documentation-for-pull-requests

View File

@ -19,7 +19,7 @@ The config for flake8 is located in setup.cfg. It specifies:
pylint
------
This is included in flake8's checks, but you can also run it separately to see a more detailed report: ::
To run pylint: ::
$ pylint <python files that you wish to lint>

View File

@ -49,11 +49,11 @@ use_docker:
postgresql_version:
Select a PostgreSQL_ version to use. The choices are:
1. 11.3
2. 10.8
3. 9.6
4. 9.5
5. 9.4
1. 12.3
2. 11.8
3. 10.8
4. 9.6
5. 9.5
js_task_runner:
Select a JavaScript task runner. The choices are:
@ -119,6 +119,7 @@ ci_tool:
1. None
2. `Travis CI`_
3. `Gitlab CI`_
4. `Github Actions`_
keep_local_envs_in_vcs:
Indicates whether the project's ``.envs/.local/`` should be kept in VCS
@ -176,3 +177,4 @@ debug:
.. _GitLab CI: https://docs.gitlab.com/ee/ci/
.. _Github Actions: https://docs.github.com/en/actions

View File

@ -49,6 +49,8 @@ DJANGO_AWS_S3_CUSTOM_DOMAIN AWS_S3_CUSTOM_DOMAIN n/a
DJANGO_GCP_STORAGE_BUCKET_NAME GS_BUCKET_NAME n/a raises error
GOOGLE_APPLICATION_CREDENTIALS n/a n/a raises error
SENTRY_DSN SENTRY_DSN n/a raises error
SENTRY_ENVIRONMENT n/a n/a production
SENTRY_TRACES_SAMPLE_RATE n/a n/a 0.0
DJANGO_SENTRY_LOG_LEVEL SENTRY_LOG_LEVEL n/a logging.INFO
MAILGUN_API_KEY MAILGUN_API_KEY n/a raises error
MAILGUN_DOMAIN MAILGUN_SENDER_DOMAIN n/a raises error

View File

@ -75,6 +75,11 @@ 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")
def remove_gulp_files():
@ -118,6 +123,10 @@ def remove_dotgitlabciyml_file():
os.remove(".gitlab-ci.yml")
def remove_dotgithub_folder():
shutil.rmtree(".github")
def append_to_project_gitignore(path):
gitignore_file_path = ".gitignore"
with open(gitignore_file_path, "a") as gitignore_file:
@ -346,6 +355,8 @@ def main():
if "{{ cookiecutter.use_heroku }}".lower() == "n":
remove_heroku_files()
elif "{{ cookiecutter.use_compressor }}".lower() == "n":
remove_heroku_build_hooks()
if (
"{{ cookiecutter.use_docker }}".lower() == "n"
@ -388,6 +399,9 @@ def main():
if "{{ cookiecutter.ci_tool }}".lower() != "gitlab":
remove_dotgitlabciyml_file()
if "{{ cookiecutter.ci_tool }}".lower() != "github":
remove_dotgithub_folder()
if "{{ cookiecutter.use_drf }}".lower() == "n":
remove_drf_starter_files()

View File

@ -1,17 +1,23 @@
cookiecutter==1.7.2
sh==1.13.1
sh==1.14.1
binaryornot==0.4.4
# Code quality
# ------------------------------------------------------------------------------
black==19.10b0
flake8==3.8.3
flake8-isort==3.0.0
black==20.8b1
isort==5.6.4
flake8==3.8.4
flake8-isort==4.0.0
# Testing
# ------------------------------------------------------------------------------
tox==3.16.1
pytest==5.4.3
tox==3.20.1
pytest==5.4.3 # pyup: <6 # https://github.com/hackebrot/pytest-cookies/issues/51
pytest-cookies==0.5.1
pytest-instafail==0.4.2
pyyaml==5.3.1
# Scripting
# ------------------------------------------------------------------------------
PyGithub==1.54
jinja2==2.11.2

1
scripts/__init__.py Normal file
View File

@ -0,0 +1 @@

View File

@ -0,0 +1,78 @@
import os
from pathlib import Path
from github import Github
from jinja2 import Template
import datetime as dt
CURRENT_FILE = Path(__file__)
ROOT = CURRENT_FILE.parents[1]
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN", None)
# Generate changelog for PRs merged yesterday
MERGED_DATE = dt.date.today() - dt.timedelta(days=1)
def main() -> None:
"""
Script entry point.
"""
merged_pulls = list(iter_pulls())
if not merged_pulls:
print("Nothing was merged, existing.")
return
# Group pull requests by type of change
grouped_pulls = group_pulls_by_change_type(merged_pulls)
# Generate portion of markdown
rendered_content = generate_md(grouped_pulls)
# Update CHANGELOG.md file
file_path = ROOT / "CHANGELOG.md"
old_content = file_path.read_text()
updated_content = old_content.replace(
"<!-- GENERATOR_PLACEHOLDER -->",
f"<!-- GENERATOR_PLACEHOLDER -->\n\n{rendered_content}",
)
file_path.write_text(updated_content)
def iter_pulls():
"""Fetch merged pull requests at the date we're interested in."""
repo = Github(login_or_token=GITHUB_TOKEN).get_repo("pydanny/cookiecutter-django")
recent_pulls = repo.get_pulls(
state="closed", sort="updated", direction="desc"
).get_page(0)
for pull in recent_pulls:
if pull.merged and pull.merged_at.date() == MERGED_DATE:
yield pull
def group_pulls_by_change_type(pull_requests_list):
"""Group pull request by change type."""
grouped_pulls = {
"Changed": [],
"Fixed": [],
"Updated": [],
}
for pull in pull_requests_list:
label_names = {l.name for l in pull.labels}
if "update" in label_names:
group_name = "Updated"
elif "bug" in label_names:
group_name = "Fixed"
else:
group_name = "Changed"
grouped_pulls[group_name].append(pull)
return grouped_pulls
def generate_md(grouped_pulls):
"""Generate markdown file from Jinja template."""
changelog_template = ROOT / ".github" / "changelog-template.md"
template = Template(changelog_template.read_text(), autoescape=True)
return template.render(merge_date=MERGED_DATE, grouped_pulls=grouped_pulls)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,104 @@
import json
from pathlib import Path
from github import Github
from github.NamedUser import NamedUser
from jinja2 import Template
CURRENT_FILE = Path(__file__)
ROOT = CURRENT_FILE.parents[1]
BOT_LOGINS = ["pyup-bot"]
def main() -> None:
"""
Script entry point.
1. Fetch recent contributors from the Github API
2. Add missing ones to the JSON file
3. Generate Markdown from JSON file
"""
recent_authors = set(iter_recent_authors())
# Add missing users to the JSON file
contrib_file = ContributorsJSONFile()
for author in recent_authors:
print(f"Checking if {author.login} should be added")
if author.login not in contrib_file:
contrib_file.add_contributor(author)
print(f"Added {author.login} to contributors")
contrib_file.save()
# Generate MD file from JSON file
write_md_file(contrib_file.content)
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.
"""
repo = Github(per_page=5).get_repo("pydanny/cookiecutter-django")
recent_pulls = repo.get_pulls(
state="closed", sort="updated", direction="desc"
).get_page(0)
for pull in recent_pulls:
if (
pull.merged
and pull.user.type == "User"
and pull.user.login not in BOT_LOGINS
):
yield pull.user
class ContributorsJSONFile:
"""Helper to interact with the JSON file."""
file_path = ROOT / ".github" / "contributors.json"
content = None
def __init__(self) -> None:
"""Read initial content."""
self.content = json.loads(self.file_path.read_text())
def __contains__(self, github_login: str):
"""Provide a nice API to do: `username in file`."""
return any(
# Github usernames are case insensitive
github_login.lower() == contrib["github_login"].lower()
for contrib in self.content
)
def add_contributor(self, user: NamedUser):
"""Append the contributor data we care about at the end."""
contributor_data = {
"name": user.name or user.login,
"github_login": user.login,
"twitter_username": user.twitter_username or "",
}
self.content.append(contributor_data)
def save(self):
"""Write the file to disk with indentation."""
text_content = json.dumps(self.content, indent=2, ensure_ascii=False)
self.file_path.write_text(text_content)
def write_md_file(contributors):
"""Generate markdown file from Jinja template."""
contributors_template = ROOT / ".github" / "CONTRIBUTORS-template.md"
template = Template(contributors_template.read_text(), autoescape=True)
core_contributors = [c for c in contributors if c.get("is_core", False)]
other_contributors = (c for c in contributors if not c.get("is_core", False))
other_contributors = sorted(other_contributors, key=lambda c: c["name"].lower())
content = template.render(
core_contributors=core_contributors, other_contributors=other_contributors
)
file_path = ROOT / "CONTRIBUTORS.md"
file_path.write_text(content)
if __name__ == "__main__":
main()

View File

@ -10,7 +10,7 @@ except ImportError:
# Our version ALWAYS matches the version of Django we support
# If Django has a new release, we branch, tag, then update this setting after the tag.
version = "3.0.7"
version = "3.0.11"
if sys.argv[-1] == "tag":
os.system(f'git tag -a {version} -m "version {version}"')

View File

@ -1,9 +1,14 @@
#!/bin/sh
# this is a very simple script that tests the docker configuration for cookiecutter-django
# it is meant to be run from the root directory of the repository, eg:
# sh tests/test_docker.sh
# sh tests/test_bare.sh
set -o errexit
set -x
# Install modern pip with new resolver:
# https://blog.python.org/2020/11/pip-20-3-release-new-resolver.html
pip install 'pip>=20.3'
# install test requirements
pip install -r requirements.txt

View File

@ -37,11 +37,11 @@ SUPPORTED_COMBINATIONS = [
{"use_pycharm": "n"},
{"use_docker": "y"},
{"use_docker": "n"},
{"postgresql_version": "11.3"},
{"postgresql_version": "12.3"},
{"postgresql_version": "11.8"},
{"postgresql_version": "10.8"},
{"postgresql_version": "9.6"},
{"postgresql_version": "9.5"},
{"postgresql_version": "9.4"},
{"cloud_provider": "AWS", "use_whitenoise": "y"},
{"cloud_provider": "AWS", "use_whitenoise": "n"},
{"cloud_provider": "GCP", "use_whitenoise": "y"},
@ -96,6 +96,7 @@ SUPPORTED_COMBINATIONS = [
{"ci_tool": "None"},
{"ci_tool": "Travis"},
{"ci_tool": "Gitlab"},
{"ci_tool": "Github"},
{"keep_local_envs_in_vcs": "y"},
{"keep_local_envs_in_vcs": "n"},
{"debug": "y"},
@ -132,13 +133,13 @@ def check_paths(paths):
for line in open(path, "r"):
match = RE_OBJ.search(line)
msg = "cookiecutter variable not replaced in {}"
assert match is None, msg.format(path)
assert match is None, f"cookiecutter variable not replaced in {path}"
@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id)
def test_project_generation(cookies, context, context_override):
"""Test that project is generated and fully rendered."""
result = cookies.bake(extra_context={**context, **context_override})
assert result.exit_code == 0
assert result.exception is None
@ -176,7 +177,10 @@ def test_black_passes(cookies, context_override):
@pytest.mark.parametrize(
["use_docker", "expected_test_script"],
[("n", "pytest"), ("y", "docker-compose -f local.yml run django pytest"),],
[
("n", "pytest"),
("y", "docker-compose -f local.yml run django pytest"),
],
)
def test_travis_invokes_pytest(cookies, context, use_docker, expected_test_script):
context.update({"ci_tool": "Travis", "use_docker": use_docker})
@ -189,7 +193,7 @@ def test_travis_invokes_pytest(cookies, context, use_docker, expected_test_scrip
with open(f"{result.project}/.travis.yml", "r") as travis_yml:
try:
yml = yaml.load(travis_yml, Loader=yaml.FullLoader)["jobs"]["include"]
yml = yaml.safe_load(travis_yml)["jobs"]["include"]
assert yml[0]["script"] == ["flake8"]
assert yml[1]["script"] == [expected_test_script]
except yaml.YAMLError as e:
@ -198,7 +202,10 @@ def test_travis_invokes_pytest(cookies, context, use_docker, expected_test_scrip
@pytest.mark.parametrize(
["use_docker", "expected_test_script"],
[("n", "pytest"), ("y", "docker-compose -f local.yml run django pytest"),],
[
("n", "pytest"),
("y", "docker-compose -f local.yml run django pytest"),
],
)
def test_gitlab_invokes_flake8_and_pytest(
cookies, context, use_docker, expected_test_script
@ -213,13 +220,49 @@ def test_gitlab_invokes_flake8_and_pytest(
with open(f"{result.project}/.gitlab-ci.yml", "r") as gitlab_yml:
try:
gitlab_config = yaml.load(gitlab_yml, Loader=yaml.FullLoader)
gitlab_config = yaml.safe_load(gitlab_yml)
assert gitlab_config["flake8"]["script"] == ["flake8"]
assert gitlab_config["pytest"]["script"] == [expected_test_script]
except yaml.YAMLError as e:
pytest.fail(e)
@pytest.mark.parametrize(
["use_docker", "expected_test_script"],
[
("n", "pytest"),
("y", "docker-compose -f local.yml exec -T django pytest"),
],
)
def test_github_invokes_flake8_and_pytest(
cookies, context, use_docker, expected_test_script
):
context.update({"ci_tool": "Github", "use_docker": use_docker})
result = cookies.bake(extra_context=context)
assert result.exit_code == 0
assert result.exception is None
assert result.project.basename == context["project_slug"]
assert result.project.isdir()
with open(f"{result.project}/.github/workflows/ci.yml", "r") as github_yml:
try:
github_config = yaml.safe_load(github_yml)
flake8_present = False
for action_step in github_config["jobs"]["flake8"]["steps"]:
if action_step.get("run") == "flake8":
flake8_present = True
assert flake8_present
expected_test_script_present = False
for action_step in github_config["jobs"]["pytest"]["steps"]:
if action_step.get("run") == expected_test_script:
expected_test_script_present = True
assert expected_test_script_present
except yaml.YAMLError as e:
pytest.fail(e)
@pytest.mark.parametrize("slug", ["project slug", "Project_Slug"])
def test_invalid_slug(cookies, context, slug):
"""Invalid slug should failed pre-generation hook."""

View File

@ -4,6 +4,7 @@
# sh tests/test_docker.sh
set -o errexit
set -x
# install test requirements
pip install -r requirements.txt

View File

@ -8,4 +8,4 @@ commands = pytest {posargs:./tests}
[testenv:black-template]
deps = black
commands = black --check hooks tests setup.py docs
commands = black --check hooks tests setup.py docs scripts

View File

@ -0,0 +1,7 @@
version: 2
updates:
# Update Github actions in workflows
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"

View File

@ -0,0 +1,95 @@
name: CI
# Enable Buildkit and let compose use it to speed up image building
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
on:
pull_request:
branches: [ "master" ]
paths-ignore: [ "docs/**" ]
push:
branches: [ "master" ]
paths-ignore: [ "docs/**" ]
jobs:
flake8:
runs-on: ubuntu-latest
steps:
- name: Checkout Code Repository
uses: actions/checkout@v2
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install flake8
run: |
python -m pip install --upgrade pip
pip install flake8
- name: Lint with flake8
run: flake8
# With no caching at all the entire ci process takes 4m 30s to complete!
pytest:
runs-on: ubuntu-latest
steps:
- name: Checkout Code Repository
uses: actions/checkout@v2
{% if cookiecutter.use_docker == 'y' -%}
- name: Build the Stack
run: docker-compose -f local.yml build
- name: Make DB Migrations
run: docker-compose -f local.yml run --rm django python manage.py migrate
- name: Run the Stack
run: docker-compose -f local.yml up -d
- name: Run Django Tests
run: docker-compose -f local.yml exec -T django pytest
- name: Tear down the Stack
run: docker-compose down
{%- else %}
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Get pip cache dir
id: pip-cache-location
run: |
echo "::set-output name=dir::$(pip cache dir)"
{% raw %}
- name: Cache pip Project Dependencies
uses: actions/cache@v2
with:
# Get the location of pip cache dir
path: ${{ steps.pip-cache-location.outputs.dir }}
# Look to see if there is a cache hit for the corresponding requirements file
key: ${{ runner.os }}-pip-${{ hashFiles('**/local.txt') }}
restore-keys: |
${{ runner.os }}-pip-
{% endraw %}
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements/local.txt
- name: Test with pytest
run: pytest
{%- endif %}

View File

@ -321,19 +321,6 @@ Session.vim
# Auto-generated tag files
tags
{% if cookiecutter.use_docker == 'n' %}
### VirtualEnv template
# Virtualenv
[Bb]in
[Ii]nclude
[Ll]ib
[Ll]ib64
[Ss]cripts
pyvenv.cfg
pip-selfcheck.json
.env
{% endif %}
### Project template
{% if cookiecutter.use_mailhog == 'y' and cookiecutter.use_docker == 'n' %}

View File

@ -13,7 +13,7 @@ variables:
flake8:
stage: lint
image: python:3.7-alpine
image: python:3.8-alpine
before_script:
- pip install -q flake8
script:
@ -21,7 +21,7 @@ flake8:
pytest:
stage: test
image: python:3.7
image: python:3.8
{% if cookiecutter.use_docker == 'y' -%}
image: docker/compose:latest
tags:
@ -39,7 +39,7 @@ pytest:
tags:
- python
services:
- postgres:11
- postgres:{{ cookiecutter.postgresql_version }}
variables:
DATABASE_URL: pgsql://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres/$POSTGRES_DB

View File

@ -4,19 +4,24 @@ fail_fast: true
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: master
rev: v3.3.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- repo: https://github.com/psf/black
rev: 19.10b0
rev: 20.8b1
hooks:
- id: black
- repo: https://github.com/timothycrosley/isort
rev: 5.6.4
hooks:
- id: isort
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.3
rev: 3.8.4
hooks:
- id: flake8
args: ['--config=setup.cfg']

View File

@ -0,0 +1,9 @@
version: 2
sphinx:
configuration: docs/conf.py
python:
version: 3.8
install:
- requirements: requirements/local.txt

View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
compress_enabled() {
python << END
import sys
from environ import Env
env = Env(COMPRESS_ENABLED=(bool, True))
if env('COMPRESS_ENABLED'):
sys.exit(0)
else:
sys.exit(1)
END
}
if compress_enabled
then
python manage.py compress
fi
python manage.py collectstatic --noinput

View File

@ -0,0 +1,31 @@
FROM python:3.8-slim-buster
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1
RUN apt-get update \
# dependencies for building Python packages
&& apt-get install -y build-essential \
# psycopg2 dependencies
&& apt-get install -y libpq-dev \
# Translations dependencies
&& apt-get install -y gettext \
# Uncomment below lines to enable Sphinx output to latex and pdf
# && apt-get install -y texlive-latex-recommended \
# && apt-get install -y texlive-fonts-recommended \
# && apt-get install -y texlive-latex-extra \
# && apt-get install -y latexmk \
# cleaning up unused files
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
&& rm -rf /var/lib/apt/lists/*
# Requirements are installed here to ensure they will be cached.
COPY ./requirements /requirements
# All imports needed for autodoc.
RUN pip install -r /requirements/local.txt -r /requirements/production.txt
COPY ./compose/local/docs/start /start-docs
RUN sed -i 's/\r$//g' /start-docs
RUN chmod +x /start-docs
WORKDIR /docs

View File

@ -0,0 +1,7 @@
#!/bin/bash
set -o errexit
set -o pipefail
set -o nounset
make livehtml

View File

@ -32,26 +32,26 @@ COPY ./requirements /requirements
RUN pip install --no-cache-dir -r /requirements/production.txt \
&& rm -rf /requirements
COPY ./compose/production/django/entrypoint /entrypoint
COPY --chown=django:django ./compose/production/django/entrypoint /entrypoint
RUN sed -i 's/\r$//g' /entrypoint
RUN chmod +x /entrypoint
RUN chown django /entrypoint
COPY ./compose/production/django/start /start
COPY --chown=django:django ./compose/production/django/start /start
RUN sed -i 's/\r$//g' /start
RUN chmod +x /start
RUN chown django /start
{%- if cookiecutter.use_celery == "y" %}
COPY ./compose/production/django/celery/worker/start /start-celeryworker
COPY --chown=django:django ./compose/production/django/celery/worker/start /start-celeryworker
RUN sed -i 's/\r$//g' /start-celeryworker
RUN chmod +x /start-celeryworker
RUN chown django /start-celeryworker
COPY ./compose/production/django/celery/beat/start /start-celerybeat
COPY --chown=django:django ./compose/production/django/celery/beat/start /start-celerybeat
RUN sed -i 's/\r$//g' /start-celerybeat
RUN chmod +x /start-celerybeat
RUN chown django /start-celerybeat
COPY ./compose/production/django/celery/flower/start /start-flower
RUN sed -i 's/\r$//g' /start-flower

View File

@ -1,5 +1,5 @@
FROM traefik:v2.0
RUN mkdir -p /etc/traefik/acme
RUN touch /etc/traefik/acme/acme.json
RUN chmod 600 /etc/traefik/acme/acme.json
FROM traefik:v2.2.11
RUN mkdir -p /etc/traefik/acme \
&& touch /etc/traefik/acme/acme.json \
&& chmod 600 /etc/traefik/acme/acme.json
COPY ./compose/production/traefik/traefik.yml /etc/traefik

View File

@ -80,6 +80,7 @@ THIRD_PARTY_APPS = [
{%- if cookiecutter.use_drf == "y" %}
"rest_framework",
"rest_framework.authtoken",
"corsheaders",
{%- endif %}
]
@ -134,6 +135,9 @@ AUTH_PASSWORD_VALIDATORS = [
# https://docs.djangoproject.com/en/dev/ref/settings/#middleware
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
{%- if cookiecutter.use_drf == 'y' %}
"corsheaders.middleware.CorsMiddleware",
{%- endif %}
{%- if cookiecutter.use_whitenoise == 'y' %}
"whitenoise.middleware.WhiteNoiseMiddleware",
{%- endif %}
@ -321,6 +325,10 @@ REST_FRAMEWORK = {
),
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
}
# django-cors-headers - https://github.com/adamchainz/django-cors-headers#setup
CORS_URLS_REGEX = r"^/api/.*$"
{%- endif %}
# Your stuff...
# ------------------------------------------------------------------------------

View File

@ -34,7 +34,7 @@ CACHES = {
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
# Mimicing memcache behavior.
# http://jazzband.github.io/django-redis/latest/#_memcached_exceptions_behavior
# https://github.com/jazzband/django-redis#memcached-exceptions-behavior
"IGNORE_EXCEPTIONS": True,
},
}
@ -86,8 +86,6 @@ _AWS_EXPIRY = 60 * 60 * 24 * 7
AWS_S3_OBJECT_PARAMETERS = {
"CacheControl": f"max-age={_AWS_EXPIRY}, s-maxage={_AWS_EXPIRY}, must-revalidate"
}
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_DEFAULT_ACL = None
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_S3_REGION_NAME = env("DJANGO_AWS_S3_REGION_NAME", default=None)
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#cloudfront
@ -235,13 +233,12 @@ ANYMAIL = {}
# ------------------------------------------------------------------------------
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_ENABLED
COMPRESS_ENABLED = env.bool("COMPRESS_ENABLED", default=True)
{%- if cookiecutter.cloud_provider == 'None' %}
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_STORAGE
{%- if cookiecutter.cloud_provider == 'AWS' %}
COMPRESS_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
{%- elif cookiecutter.cloud_provider == 'GCP' %}
COMPRESS_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
{%- elif cookiecutter.cloud_provider == 'None' %}
COMPRESS_STORAGE = "compressor.storage.GzipCompressorFileStorage"
{%- elif cookiecutter.cloud_provider in ('AWS', 'GCP') and cookiecutter.use_whitenoise == 'n' %}
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_STORAGE
COMPRESS_STORAGE = STATICFILES_STORAGE
{%- endif %}
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_URL
COMPRESS_URL = STATIC_URL{% if cookiecutter.use_whitenoise == 'y' or cookiecutter.cloud_provider == 'None' %} # noqa F405{% endif %}
@ -354,13 +351,17 @@ sentry_logging = LoggingIntegration(
)
{%- if cookiecutter.use_celery == 'y' %}
integrations = [sentry_logging, DjangoIntegration(), CeleryIntegration()]
{% else %}
integrations = [sentry_logging, DjangoIntegration()]
{% endif -%}
sentry_sdk.init(
dsn=SENTRY_DSN,
integrations=[sentry_logging, DjangoIntegration(), CeleryIntegration()],
integrations=integrations,
environment=env("SENTRY_ENVIRONMENT", default="production"),
traces_sample_rate=env.float("SENTRY_TRACES_SAMPLE_RATE", default=0.0),
)
{% else %}
sentry_sdk.init(dsn=SENTRY_DSN, integrations=[sentry_logging, DjangoIntegration()])
{% endif -%}
{% endif %}
# Your stuff...
# ------------------------------------------------------------------------------

View File

@ -3,18 +3,38 @@
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build -c .
SOURCEDIR = .
BUILDDIR = _build
BUILDDIR = ./_build
{%- if cookiecutter.use_docker == 'y' %}
APP = /app
{%- else %}
APP = ../{{cookiecutter.project_slug}}
{% endif %}
.PHONY: help livehtml apidocs Makefile
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@$(SPHINXBUILD) help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Build, watch and serve docs with live reload
livehtml:
sphinx-autobuild -b html
{%- if cookiecutter.use_docker == 'y' %} --host 0.0.0.0
{%- else %} --open-browser
{%- endif %} --port 7000 --watch $(APP) -c . $(SOURCEDIR) $(BUILDDIR)/html
# Outputs rst files from django application code
apidocs:
{%- if cookiecutter.use_docker == 'y' %}
sphinx-apidoc -o $(SOURCEDIR)/api /app
{%- else %}
sphinx-apidoc -o $(SOURCEDIR)/api ../{{cookiecutter.project_slug}}
{%- endif %}
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@$(SPHINXBUILD) -b $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

View File

@ -9,15 +9,27 @@
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
import django
# import django
# sys.path.insert(0, os.path.abspath('..'))
# os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
# django.setup()
if os.getenv("READTHEDOCS", default=False) == "True":
sys.path.insert(0, os.path.abspath(".."))
os.environ["DJANGO_READ_DOT_ENV_FILE"] = "True"
os.environ["USE_DOCKER"] = "no"
else:
{%- if cookiecutter.use_docker == 'y' %}
sys.path.insert(0, os.path.abspath("/app"))
{%- else %}
sys.path.insert(0, os.path.abspath(".."))
{%- endif %}
os.environ["DATABASE_URL"] = "sqlite:///readthedocs.db"
{%- if cookiecutter.use_celery == 'y' %}
os.environ["CELERY_BROKER_URL"] = os.getenv("REDIS_URL", "redis://redis:6379")
{%- endif %}
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
django.setup()
# -- Project information -----------------------------------------------------
@ -31,17 +43,19 @@ author = "{{ cookiecutter.author_name }}"
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.napoleon",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# templates_path = ["_templates"]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
@ -52,4 +66,4 @@ html_theme = "alabaster"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
# html_static_path = ["_static"]

View File

@ -0,0 +1,46 @@
How To - Project Documentation
======================================================================
Get Started
----------------------------------------------------------------------
Documentation can be written as rst files in the `{{cookiecutter.project_slug}}/docs/_source`.
{% if cookiecutter.use_docker == 'n' %}
To build and serve docs, use the command:
::
make livehtml
from inside the `{{cookiecutter.project_slug}}/docs` directory.
{% else %}
To build and serve docs, use the commands:
::
docker-compose -f local.yml up docs
{% endif %}
Changes to files in `docs/_source` will be picked up and reloaded automatically.
`Sphinx <https://www.sphinx-doc.org/>`_ is the tool used to build documentation.
Docstrings to Documentation
----------------------------------------------------------------------
The sphinx extension `apidoc <https://www.sphinx-doc.org/en/master/man/sphinx-apidoc.html/>`_ is used to automatically document code using signatures and docstrings.
Numpy or Google style docstrings will be picked up from project files and availble for documentation. See the `Napoleon <https://sphinxcontrib-napoleon.readthedocs.io/en/latest/>`_ extension for details.
For an in-use example, see the `page source <_sources/users.rst.txt>`_ for :ref:`users`.
To compile all docstrings automatically into documentation source files, use the command:
::
make apidocs
{% if cookiecutter.use_docker == 'y' %}
This can be done in the docker container:
::
docker run --rm docs make apidocs
{% endif -%}

View File

@ -10,7 +10,9 @@ Welcome to {{ cookiecutter.project_name }}'s documentation!
:maxdepth: 2
:caption: Contents:
howto
pycharm/configuration
users

View File

@ -4,11 +4,13 @@ pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
set SPHINXBUILD=sphinx-build -c .
)
set SOURCEDIR=.
set SOURCEDIR=_source
set BUILDDIR=_build
set APP=..\{{cookiecutter.project_slug}}
if "%1" == "" goto help
@ -20,16 +22,25 @@ if errorlevel 9009 (
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.Install sphinx-autobuild for live serving.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
%SPHINXBUILD% -b %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:livehtml
sphinx-autobuild -b html --open-browser -p 7000 --watch %APP% -c . %SOURCEDIR% %BUILDDIR%/html
GOTO :EOF
:apidocs
sphinx-apidoc -o %SOURCEDIR%/api %APP%
GOTO :EOF
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
%SPHINXBUILD% -b help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

View File

@ -0,0 +1,15 @@
.. _users:
Users
======================================================================
Starting a new project, its highly recommended to set up a custom user model,
even if the default User model is sufficient for you.
This model behaves identically to the default user model,
but youll be able to customize it in the future if the need arises.
.. automodule:: {{cookiecutter.project_slug}}.users.models
:members:
:noindex:

View File

@ -163,9 +163,9 @@ function initBrowserSync() {
// Watch
function watchPaths() {
watch(`${paths.sass}/*.scss`, styles)
watch(`${paths.templates}/**/*.html`).on("change", reload)
watch([`${paths.js}/*.js`, `!${paths.js}/*.min.js`], scripts).on("change", reload)
watch(`${paths.sass}/*.scss`{% if cookiecutter.windows == 'y' %}, { usePolling: true }{% endif %}, styles)
watch(`${paths.templates}/**/*.html`{% if cookiecutter.windows == 'y' %}, { usePolling: true }{% endif %}).on("change", reload)
watch([`${paths.js}/*.js`, `!${paths.js}/*.min.js`]{% if cookiecutter.windows == 'y' %}, { usePolling: true }{% endif %}, scripts).on("change", reload)
}
// Generate all assets

View File

@ -17,7 +17,7 @@ services:
- mailhog
{%- endif %}
volumes:
- .:/app
- .:/app:z
env_file:
- ./.envs/.local/.django
- ./.envs/.local/.postgres
@ -32,10 +32,27 @@ services:
image: {{ cookiecutter.project_slug }}_production_postgres
container_name: postgres
volumes:
- local_postgres_data:/var/lib/postgresql/data
- local_postgres_data_backups:/backups
- local_postgres_data:/var/lib/postgresql/data:Z
- local_postgres_data_backups:/backups:z
env_file:
- ./.envs/.local/.postgres
docs:
image: {{ cookiecutter.project_slug }}_local_docs
container_name: docs
build:
context: .
dockerfile: ./compose/local/docs/Dockerfile
env_file:
- ./.envs/.local/.django
volumes:
- ./docs:/docs:z
- ./config:/app/config:z
- ./{{ cookiecutter.project_slug }}:/app/{{ cookiecutter.project_slug }}:z
ports:
- "7000:7000"
command: /start-docs
{%- if cookiecutter.use_mailhog == 'y' %}
mailhog:
@ -97,7 +114,7 @@ services:
depends_on:
- django
volumes:
- .:/app
- .:/app:z
# http://jdlm.info/articles/2016/03/06/lessons-building-node-app-docker.html
- /app/node_modules
command: npm run dev

View File

@ -25,8 +25,8 @@ services:
dockerfile: ./compose/production/postgres/Dockerfile
image: {{ cookiecutter.project_slug }}_production_postgres
volumes:
- production_postgres_data:/var/lib/postgresql/data
- production_postgres_data_backups:/backups
- production_postgres_data:/var/lib/postgresql/data:Z
- production_postgres_data_backups:/backups:z
env_file:
- ./.envs/.production/.postgres
@ -38,7 +38,7 @@ services:
depends_on:
- django
volumes:
- production_traefik:/etc/traefik/acme
- production_traefik:/etc/traefik/acme:z
ports:
- "0.0.0.0:80:80"
- "0.0.0.0:443:443"
@ -75,5 +75,5 @@ services:
env_file:
- ./.envs/.production/.django
volumes:
- production_postgres_data_backups:/backups
- production_postgres_data_backups:/backups:z
{%- endif %}

View File

@ -1,40 +1,46 @@
pytz==2020.1 # https://github.com/stub42/pytz
python-slugify==4.0.0 # https://github.com/un33k/python-slugify
Pillow==7.1.2 # https://github.com/python-pillow/Pillow
pytz==2020.4 # https://github.com/stub42/pytz
python-slugify==4.0.1 # https://github.com/un33k/python-slugify
Pillow==8.0.1 # https://github.com/python-pillow/Pillow
{%- if cookiecutter.use_compressor == "y" %}
rcssmin==1.0.6{% if cookiecutter.windows == 'y' and cookiecutter.use_docker == 'n' %} --install-option="--without-c-extensions"{% endif %} # https://github.com/ndparker/rcssmin
{%- if cookiecutter.windows == 'y' and cookiecutter.use_docker == 'n' %}
rcssmin==1.0.6 --install-option="--without-c-extensions" # https://github.com/ndparker/rcssmin
{%- else %}
rcssmin==1.0.6 # https://github.com/ndparker/rcssmin
{%- endif %}
{%- endif %}
argon2-cffi==20.1.0 # https://github.com/hynek/argon2_cffi
{%- if cookiecutter.use_whitenoise == 'y' %}
whitenoise==5.1.0 # https://github.com/evansd/whitenoise
whitenoise==5.2.0 # https://github.com/evansd/whitenoise
{%- endif %}
redis==3.5.0 # https://github.com/andymccurdy/redis-py
redis==3.5.3 # https://github.com/andymccurdy/redis-py
{%- if cookiecutter.use_docker == "y" or cookiecutter.windows == "n" %}
hiredis==1.0.1 # https://github.com/redis/hiredis-py
hiredis==1.1.0 # https://github.com/redis/hiredis-py
{%- endif %}
{%- if cookiecutter.use_celery == "y" %}
celery==4.4.5 # pyup: < 5.0 # https://github.com/celery/celery
django-celery-beat==2.0.0 # https://github.com/celery/django-celery-beat
celery==4.4.6 # pyup: < 5.0,!=4.4.7 # https://github.com/celery/celery
django-celery-beat==2.1.0 # https://github.com/celery/django-celery-beat
django-timezone-field==4.0 # https://github.com/celery/django-celery-beat/pull/378
{%- if cookiecutter.use_docker == 'y' %}
flower==0.9.4 # https://github.com/mher/flower
flower==0.9.5 # https://github.com/mher/flower
{%- endif %}
{%- endif %}
{%- if cookiecutter.use_async == 'y' %}
uvicorn==0.11.5 # https://github.com/encode/uvicorn
uvicorn[standard]==0.12.3 # https://github.com/encode/uvicorn
{%- endif %}
# Django
# ------------------------------------------------------------------------------
django==3.0.7 # pyup: < 3.1 # https://www.djangoproject.com/
django==3.0.11 # pyup: < 3.1 # https://www.djangoproject.com/
django-environ==0.4.5 # https://github.com/joke2k/django-environ
django-model-utils==4.0.0 # https://github.com/jazzband/django-model-utils
django-allauth==0.42.0 # https://github.com/pennersr/django-allauth
django-crispy-forms==1.9.1 # https://github.com/django-crispy-forms/django-crispy-forms
django-model-utils==4.1.1 # https://github.com/jazzband/django-model-utils
django-allauth==0.44.0 # https://github.com/pennersr/django-allauth
django-crispy-forms==1.10.0 # https://github.com/django-crispy-forms/django-crispy-forms
{%- if cookiecutter.use_compressor == "y" %}
django-compressor==2.4 # https://github.com/django-compressor/django-compressor
{%- endif %}
django-redis==4.12.1 # https://github.com/jazzband/django-redis
{%- if cookiecutter.use_drf == "y" %}
# Django REST Framework
djangorestframework==3.11.0 # https://github.com/encode/django-rest-framework
djangorestframework==3.12.2 # https://github.com/encode/django-rest-framework
django-cors-headers==3.5.0 # https://github.com/adamchainz/django-cors-headers
{%- endif %}

View File

@ -1,12 +1,11 @@
-r ./base.txt
-r base.txt
Werkzeug==1.0.1 # https://github.com/pallets/werkzeug
ipdb==0.13.3 # https://github.com/gotcha/ipdb
Sphinx==3.1.1 # https://github.com/sphinx-doc/sphinx
ipdb==0.13.4 # https://github.com/gotcha/ipdb
{%- if cookiecutter.use_docker == 'y' %}
psycopg2==2.8.5 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
psycopg2==2.8.6 # https://github.com/psycopg/psycopg2
{%- else %}
psycopg2-binary==2.8.5 # https://github.com/psycopg/psycopg2
psycopg2-binary==2.8.6 # https://github.com/psycopg/psycopg2
{%- endif %}
{%- if cookiecutter.use_async == 'y' or cookiecutter.use_celery == 'y' %}
watchgod==0.6 # https://github.com/samuelcolvin/watchgod
@ -14,28 +13,33 @@ watchgod==0.6 # https://github.com/samuelcolvin/watchgod
# Testing
# ------------------------------------------------------------------------------
mypy==0.782 # https://github.com/python/mypy
django-stubs==1.5.0 # https://github.com/typeddjango/django-stubs
pytest==5.4.3 # https://github.com/pytest-dev/pytest
pytest-sugar==0.9.3 # https://github.com/Frozenball/pytest-sugar
mypy==0.790 # https://github.com/python/mypy
django-stubs==1.7.0 # https://github.com/typeddjango/django-stubs
pytest==6.1.2 # https://github.com/pytest-dev/pytest
pytest-sugar==0.9.4 # https://github.com/Frozenball/pytest-sugar
# Documentation
# ------------------------------------------------------------------------------
sphinx==3.3.1 # https://github.com/sphinx-doc/sphinx
sphinx-autobuild==2020.9.1 # https://github.com/GaretJax/sphinx-autobuild
# Code quality
# ------------------------------------------------------------------------------
flake8==3.8.3 # https://github.com/PyCQA/flake8
flake8-isort==3.0.0 # https://github.com/gforcada/flake8-isort
coverage==5.1 # https://github.com/nedbat/coveragepy
black==19.10b0 # https://github.com/ambv/black
pylint-django==2.0.15 # https://github.com/PyCQA/pylint-django
flake8==3.8.4 # https://github.com/PyCQA/flake8
flake8-isort==4.0.0 # https://github.com/gforcada/flake8-isort
coverage==5.3 # https://github.com/nedbat/coveragepy
black==20.8b1 # https://github.com/ambv/black
pylint-django==2.3.0 # https://github.com/PyCQA/pylint-django
{%- if cookiecutter.use_celery == 'y' %}
pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery
{%- endif %}
pre-commit==2.5.1 # https://github.com/pre-commit/pre-commit
pre-commit==2.9.3 # https://github.com/pre-commit/pre-commit
# Django
# ------------------------------------------------------------------------------
factory-boy==2.12.0 # https://github.com/FactoryBoy/factory_boy
factory-boy==3.1.0 # https://github.com/FactoryBoy/factory_boy
django-debug-toolbar==2.2 # https://github.com/jazzband/django-debug-toolbar
django-extensions==3.0.0 # https://github.com/django-extensions/django-extensions
django-debug-toolbar==3.2 # https://github.com/jazzband/django-debug-toolbar
django-extensions==3.1.0 # https://github.com/django-extensions/django-extensions
django-coverage-plugin==1.8.0 # https://github.com/nedbat/django_coverage_plugin
pytest-django==3.9.0 # https://github.com/pytest-dev/pytest-django
pytest-django==4.1.0 # https://github.com/pytest-dev/pytest-django

View File

@ -1,42 +1,42 @@
# PRECAUTION: avoid production dependencies that aren't in development
-r ./base.txt
-r base.txt
gunicorn==20.0.4 # https://github.com/benoitc/gunicorn
psycopg2==2.8.5 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
psycopg2==2.8.6 # https://github.com/psycopg/psycopg2
{%- if cookiecutter.use_whitenoise == 'n' %}
Collectfast==2.2.0 # https://github.com/antonagestam/collectfast
{%- endif %}
{%- if cookiecutter.use_sentry == "y" %}
sentry-sdk==0.15.1 # https://github.com/getsentry/sentry-python
sentry-sdk==0.19.5 # https://github.com/getsentry/sentry-python
{%- endif %}
{%- if cookiecutter.use_docker == "n" and cookiecutter.windows == "y" %}
hiredis==1.0.1 # https://github.com/redis/hiredis-py
hiredis==1.1.0 # https://github.com/redis/hiredis-py
{%- endif %}
# Django
# ------------------------------------------------------------------------------
{%- if cookiecutter.cloud_provider == 'AWS' %}
django-storages[boto3]==1.9.1 # https://github.com/jschneier/django-storages
django-storages[boto3]==1.10.1 # https://github.com/jschneier/django-storages
{%- elif cookiecutter.cloud_provider == 'GCP' %}
django-storages[google]==1.9.1 # https://github.com/jschneier/django-storages
django-storages[google]==1.10.1 # https://github.com/jschneier/django-storages
{%- endif %}
{%- if cookiecutter.mail_service == 'Mailgun' %}
django-anymail[mailgun]==7.1.0 # https://github.com/anymail/django-anymail
django-anymail[mailgun]==8.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Amazon SES' %}
django-anymail[amazon_ses]==7.1.0 # https://github.com/anymail/django-anymail
django-anymail[amazon_ses]==8.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Mailjet' %}
django-anymail[mailjet]==7.1.0 # https://github.com/anymail/django-anymail
django-anymail[mailjet]==8.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Mandrill' %}
django-anymail[mandrill]==7.1.0 # https://github.com/anymail/django-anymail
django-anymail[mandrill]==8.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Postmark' %}
django-anymail[postmark]==7.1.0 # https://github.com/anymail/django-anymail
django-anymail[postmark]==8.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Sendgrid' %}
django-anymail[sendgrid]==7.1.0 # https://github.com/anymail/django-anymail
django-anymail[sendgrid]==8.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'SendinBlue' %}
django-anymail[sendinblue]==7.1.0 # https://github.com/anymail/django-anymail
django-anymail[sendinblue]==8.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'SparkPost' %}
django-anymail[sparkpost]==7.1.0 # https://github.com/anymail/django-anymail
django-anymail[sparkpost]==8.1 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Other SMTP' %}
django-anymail==7.1.0 # https://github.com/anymail/django-anymail
django-anymail==8.1 # https://github.com/anymail/django-anymail
{%- endif %}

View File

@ -1 +1 @@
python-3.8.2
python-3.8.5

View File

@ -1,10 +1,10 @@
[flake8]
max-line-length = 120
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules,venv
[pycodestyle]
max-line-length = 120
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules,venv
[mypy]
python_version = 3.8

View File

@ -5,8 +5,8 @@
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>{% block title %}{% endraw %}{{ cookiecutter.project_name }}{% raw %}{% endblock title %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<meta name="description" content="{% endraw %}{{ cookiecutter.description }}{% raw %}">
<meta name="author" content="{% endraw %}{{ cookiecutter.author_name }}{% raw %}">
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>

View File

@ -12,6 +12,8 @@ class UserAdmin(auth_admin.UserAdmin):
form = UserChangeForm
add_form = UserCreationForm
fieldsets = (("User", {"fields": ("name",)}),) + auth_admin.UserAdmin.fieldsets
fieldsets = (("User", {"fields": ("name",)}),) + tuple(
auth_admin.UserAdmin.fieldsets
)
list_display = ["username", "name", "is_superuser"]
search_fields = ["name"]

View File

@ -1,22 +1,23 @@
from django.contrib.auth import forms, get_user_model
from django.contrib.auth import forms as admin_forms
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
User = get_user_model()
class UserChangeForm(forms.UserChangeForm):
class Meta(forms.UserChangeForm.Meta):
class UserChangeForm(admin_forms.UserChangeForm):
class Meta(admin_forms.UserChangeForm.Meta):
model = User
class UserCreationForm(forms.UserCreationForm):
class UserCreationForm(admin_forms.UserCreationForm):
error_message = forms.UserCreationForm.error_messages.update(
error_message = admin_forms.UserCreationForm.error_messages.update(
{"duplicate_username": _("This username has already been taken.")}
)
class Meta(forms.UserCreationForm.Meta):
class Meta(admin_forms.UserCreationForm.Meta):
model = User
def clean_username(self):

View File

@ -1,14 +1,20 @@
from django.contrib.auth.models import AbstractUser
from django.db.models import CharField
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
class User(AbstractUser):
"""Default user for {{cookiecutter.project_name}}."""
# First Name and Last Name do not cover name patterns
# around the globe.
#: First and last name do not cover name patterns around the globe
name = CharField(_("Name of User"), blank=True, max_length=255)
def get_absolute_url(self):
"""Get url for user's detail view.
Returns:
str: URL for user detail.
"""
return reverse("users:detail", kwargs={"username": self.username})

View File

@ -1,7 +1,8 @@
from typing import Any, Sequence
from django.contrib.auth import get_user_model
from factory import DjangoModelFactory, Faker, post_generation
from factory import Faker, post_generation
from factory.django import DjangoModelFactory
class UserFactory(DjangoModelFactory):
@ -22,7 +23,7 @@ class UserFactory(DjangoModelFactory):
digits=True,
upper_case=True,
lower_case=True,
).generate(extra_kwargs={})
).generate(params={"locale": None})
)
self.set_password(password)

View File

@ -64,7 +64,7 @@ class TestUserDetailView:
def test_not_authenticated(self, user: User, rf: RequestFactory):
request = rf.get("/fake-url/")
request.user = AnonymousUser() # type: ignore
request.user = AnonymousUser()
response = user_detail_view(request, username=user.username)

View File

@ -2,7 +2,7 @@ from django.contrib import messages
from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
from django.views.generic import DetailView, RedirectView, UpdateView
User = get_user_model()

View File

@ -2,4 +2,7 @@ from django.conf import settings
def settings_context(_request):
return {"settings": settings}
"""Settings available by default to the templates context."""
# Note: we intentionally do NOT expose the entire settings
# to prevent accidental leaking of sensitive information
return {"DEBUG": settings.DEBUG}