Merge branch 'master' into upgrade/django-2.2

This commit is contained in:
Bruno Alla 2019-05-27 17:17:43 +01:00 committed by GitHub
commit 15f283bb74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 92 additions and 83 deletions

View File

@ -2,6 +2,13 @@
All enhancements and patches to Cookiecutter Django will be documented in this file. All enhancements and patches to Cookiecutter Django will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/). This project adheres to [Semantic Versioning](http://semver.org/).
## [2019-05-18]
### Removed
- Remove the user list view (@browniebroke)
### Fixed
- Static storage default ACL (@browniebroke)
## [2019-05-17] ## [2019-05-17]
### Fixed ### Fixed
- Added `LocaleMiddleware` to the list of middlewares (@tanoabeleyra) - Added `LocaleMiddleware` to the list of middlewares (@tanoabeleyra)

View File

@ -7,19 +7,19 @@ Core Developers
These contributors have commit flags for the repository, These contributors have commit flags for the repository,
and are able to accept and merge pull requests. and are able to accept and merge pull requests.
=========================== ================ =========== =========================== ================= ===========
Name Github Twitter Name Github Twitter
=========================== ================ =========== =========================== ================= ===========
Daniel Roy Greenfeld `@pydanny`_ @pydanny Daniel Roy Greenfeld `@pydanny`_ @pydanny
Audrey Roy Greenfeld* `@audreyr`_ @audreyr Audrey Roy Greenfeld* `@audreyr`_ @audreyr
Fábio C. Barrionuevo da Luz `@luzfcb`_ @luzfcb Fábio C. Barrionuevo da Luz `@luzfcb`_ @luzfcb
Saurabh Kumar `@theskumar`_ @_theskumar Saurabh Kumar `@theskumar`_ @_theskumar
Jannis Gebauer `@jayfk`_ Jannis Gebauer `@jayfk`_
Burhan Khalid `@burhan`_ @burhan Burhan Khalid `@burhan`_ @burhan
Nikita Shupeyko `@webyneter`_ @webyneter Nikita Shupeyko `@webyneter`_ @webyneter
Bruno Alla               `@browniebroke`_ @_BrunoAlla Bruno Alla               `@browniebroke`_ @_BrunoAlla
Wan Liuyang `@sfdye`_ @sfdye Wan Liuyang `@sfdye`_ @sfdye
=========================== ================ =========== =========================== ================= ===========
*Audrey is also the creator of Cookiecutter. Audrey and *Audrey is also the creator of Cookiecutter. Audrey and
Daniel are on the Cookiecutter core team.* Daniel are on the Cookiecutter core team.*
@ -87,6 +87,7 @@ Listed in alphabetical order.
Craig Margieson `@cmargieson`_ Craig Margieson `@cmargieson`_
Cristian Vargas `@cdvv7788`_ Cristian Vargas `@cdvv7788`_
Cullen Rhodes `@c-rhodes`_ Cullen Rhodes `@c-rhodes`_
Curtis St Pierre `@curtisstpierre`_ @cstpierre1388
Dan Shultz `@shultz`_ Dan Shultz `@shultz`_
Daniel Hepper `@dhepper`_ @danielhepper Daniel Hepper `@dhepper`_ @danielhepper
Daniele Tricoli `@eriol`_ Daniele Tricoli `@eriol`_
@ -143,6 +144,7 @@ Listed in alphabetical order.
Mateusz Ostaszewski `@mostaszewski`_ Mateusz Ostaszewski `@mostaszewski`_
Mathijs Hoogland `@MathijsHoogland`_ Mathijs Hoogland `@MathijsHoogland`_
Matt Braymer-Hayes `@mattayes`_ @mattayes Matt Braymer-Hayes `@mattayes`_ @mattayes
Matt Knapper `@mknapper1`_
Matt Linares Matt Linares
Matt Menzenski `@menzenski`_ Matt Menzenski `@menzenski`_
Matt Warren `@mfwarren`_ Matt Warren `@mfwarren`_
@ -221,6 +223,7 @@ Listed in alphabetical order.
.. _@chuckus: https://github.com/chuckus .. _@chuckus: https://github.com/chuckus
.. _@cmackenzie1: https://github.com/cmackenzie1 .. _@cmackenzie1: https://github.com/cmackenzie1
.. _@Collederas: https://github.com/Collederas .. _@Collederas: https://github.com/Collederas
.. _@curtisstpierre: https://github.com/curtisstpierre
.. _@davitovmasyan: https://github.com/davitovmasyan .. _@davitovmasyan: https://github.com/davitovmasyan
.. _@ddiazpinto: https://github.com/ddiazpinto .. _@ddiazpinto: https://github.com/ddiazpinto
.. _@demestav: https://github.com/demestav .. _@demestav: https://github.com/demestav
@ -260,6 +263,7 @@ Listed in alphabetical order.
.. _@msaizar: https://github.com/msaizar .. _@msaizar: https://github.com/msaizar
.. _@MathijsHoogland: https://github.com/MathijsHoogland .. _@MathijsHoogland: https://github.com/MathijsHoogland
.. _@mattayes: https://github.com/mattayes .. _@mattayes: https://github.com/mattayes
.. _@mknapper1: https://github.com/mknapper1
.. _@menzenski: https://github.com/menzenski .. _@menzenski: https://github.com/menzenski
.. _@mostaszewski: https://github.com/mostaszewski .. _@mostaszewski: https://github.com/mostaszewski
.. _@mfwarren: https://github.com/mfwarren .. _@mfwarren: https://github.com/mfwarren

View File

@ -89,7 +89,7 @@ Constraints
----------- -----------
* Only maintained 3rd party libraries are used. * Only maintained 3rd party libraries are used.
* Uses PostgreSQL everywhere (9.4 - 10.5) * Uses PostgreSQL everywhere (9.4 - 11.3)
* Environment variables for configuration (This won't work with Apache/mod_wsgi). * Environment variables for configuration (This won't work with Apache/mod_wsgi).
Support this Project! Support this Project!
@ -169,15 +169,12 @@ Answer the prompts with your own desired options_. For example::
use_heroku [n]: y use_heroku [n]: y
use_compressor [n]: y use_compressor [n]: y
Select postgresql_version: Select postgresql_version:
1 - 10.5 1 - 11.3
2 - 10.4 2 - 10.8
3 - 10.3 3 - 9.6
4 - 10.2 4 - 9.5
5 - 10.1 5 - 9.4
6 - 9.6 Choose from 1, 2, 3, 4, 5 [1]: 1
7 - 9.5
8 - 9.4
Choose from 1, 2, 3, 4, 5, 6, 7, 8 [1]: 1
Select js_task_runner: Select js_task_runner:
1 - None 1 - None
2 - Gulp 2 - Gulp
@ -185,7 +182,8 @@ Answer the prompts with your own desired options_. For example::
Select cloud_provider: Select cloud_provider:
1 - AWS 1 - AWS
2 - GCS 2 - GCS
Choose from 1, 2 [1]: 1 3 - None
Choose from 1, 2, 3 [1]: 1
custom_bootstrap_compilation [n]: n custom_bootstrap_compilation [n]: n
Select open_source_license: Select open_source_license:
1 - MIT 1 - MIT

View File

@ -18,11 +18,8 @@
"use_pycharm": "n", "use_pycharm": "n",
"use_docker": "n", "use_docker": "n",
"postgresql_version": [ "postgresql_version": [
"10.5", "11.3",
"10.4", "10.8",
"10.3",
"10.2",
"10.1",
"9.6", "9.6",
"9.5", "9.5",
"9.4" "9.4"
@ -33,7 +30,8 @@
], ],
"cloud_provider": [ "cloud_provider": [
"AWS", "AWS",
"GCE" "GCE",
"None"
], ],
"custom_bootstrap_compilation": "n", "custom_bootstrap_compilation": "n",
"use_compressor": "n", "use_compressor": "n",

View File

@ -35,7 +35,15 @@ Configuring the Stack
The majority of services above are configured through the use of environment variables. Just check out :ref:`envs` and you will know the drill. The majority of services above are configured through the use of environment variables. Just check out :ref:`envs` and you will know the drill.
To obtain logs and information about crashes in a production setup, make sure that you have access to an external Sentry instance (e.g. by creating an account with `sentry.io`_), and set the ``SENTRY_DSN`` variable. To obtain logs and information about crashes in a production setup, make sure that you have access to an external Sentry instance (e.g. by creating an account with `sentry.io`_), and set the ``SENTRY_DSN`` variable. Logs of level `logging.ERROR` are sent as Sentry events. Therefore, in order to send a Sentry event use:
.. code-block:: python
import logging
logging.error("This event is sent to Sentry", extra={"<example_key>": "<example_value>"})
The `extra` parameter allows you to send additional information about the context of this error.
You will probably also need to setup the Mail backend, for example by adding a `Mailgun`_ API key and a `Mailgun`_ sender domain, otherwise, the account creation view will crash and result in a 500 error when the backend attempts to send an email to the account owner. You will probably also need to setup the Mail backend, for example by adding a `Mailgun`_ API key and a `Mailgun`_ sender domain, otherwise, the account creation view will crash and result in a 500 error when the backend attempts to send an email to the account owner.

View File

@ -49,14 +49,11 @@ use_docker:
postgresql_version: postgresql_version:
Select a PostgreSQL_ version to use. The choices are: Select a PostgreSQL_ version to use. The choices are:
1. 10.5 1. 11.3
2. 10.4 2. 10.8
3. 10.3 3. 9.6
4. 10.2 4. 9.5
5. 10.1 5. 9.4
6. 9.6
7. 9.5
8. 9.4
js_task_runner: js_task_runner:
Select a JavaScript task runner. The choices are: Select a JavaScript task runner. The choices are:
@ -69,6 +66,7 @@ cloud_provider:
1. AWS_ 1. AWS_
2. GCS_ 2. GCS_
3. None
custom_bootstrap_compilation: custom_bootstrap_compilation:
Indicates whether the project should support Bootstrap recompilation Indicates whether the project should support Bootstrap recompilation
@ -100,7 +98,7 @@ use_travisci:
keep_local_envs_in_vcs: keep_local_envs_in_vcs:
Indicates whether the project's ``.envs/.local/`` should be kept in VCS Indicates whether the project's ``.envs/.local/`` should be kept in VCS
(comes in handy when working in teams where local environment reproducibility (comes in handy when working in teams where local environment reproducibility
is strongly encouraged). is strongly encouraged).
Note: .env(s) are only utilized when Docker Compose and/or Heroku support is enabled. Note: .env(s) are only utilized when Docker Compose and/or Heroku support is enabled.
debug: debug:

View File

@ -328,6 +328,12 @@ def main():
if "{{ cookiecutter.use_docker }}".lower() == "y": if "{{ cookiecutter.use_docker }}".lower() == "y":
remove_node_dockerfile() remove_node_dockerfile()
if "{{ cookiecutter.cloud_provider}}".lower() == "none":
print(
WARNING + "You chose not to use a cloud provider, "
"media files won't be served in production." + TERMINATOR
)
if "{{ cookiecutter.use_celery }}".lower() == "n": if "{{ cookiecutter.use_celery }}".lower() == "n":
remove_celery_files() remove_celery_files()
if "{{ cookiecutter.use_docker }}".lower() == "y": if "{{ cookiecutter.use_docker }}".lower() == "y":

View File

@ -1,3 +1,6 @@
[pytest] [pytest]
python_paths = . python_paths = .
norecursedirs = .tox .git */migrations/* */static/* docs venv */{{cookiecutter.project_slug}}/* norecursedirs = .tox .git */migrations/* */static/* docs venv */{{cookiecutter.project_slug}}/*
markers =
flake8: Run flake8 on all possible template combinations
black: Run black on all possible template combinations

View File

@ -5,11 +5,11 @@ binaryornot==0.4.4
# Code quality # Code quality
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
black==19.3b0 black==19.3b0
flake8==3.7.6 flake8==3.7.7
# Testing # Testing
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
tox==3.11.1 tox==3.12.1
pytest==4.5.0 pytest==4.5.0
pytest_cases==1.6.2 pytest_cases==1.6.2
pytest-cookies==0.3.0 pytest-cookies==0.3.0

View File

@ -7,11 +7,11 @@ import sh
import yaml import yaml
from binaryornot.check import is_binary from binaryornot.check import is_binary
PATTERN = "{{(\s?cookiecutter)[.](.*?)}}" PATTERN = r"{{(\s?cookiecutter)[.](.*?)}}"
RE_OBJ = re.compile(PATTERN) RE_OBJ = re.compile(PATTERN)
YN_CHOICES = ["y", "n"] YN_CHOICES = ["y", "n"]
CLOUD_CHOICES = ["AWS", "GCE"] CLOUD_CHOICES = ["AWS", "GCE", "None"]
@pytest.fixture @pytest.fixture

View File

@ -17,7 +17,7 @@ defaultEntryPoints = ["http", "https"]
[acme] [acme]
# Email address used for registration # Email address used for registration
email = "{{ cookiecutter.email }}" email = "{{ cookiecutter.email }}"
storageFile = "/etc/traefik/acme/acme.json" storage = "/etc/traefik/acme/acme.json"
entryPoint = "https" entryPoint = "https"
onDemand = false onDemand = false
OnHostRule = true OnHostRule = true

View File

@ -266,10 +266,10 @@ CELERY_TASK_SERIALIZER = "json"
CELERY_RESULT_SERIALIZER = "json" CELERY_RESULT_SERIALIZER = "json"
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-time-limit # http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-time-limit
# TODO: set to whatever value is adequate in your circumstances # TODO: set to whatever value is adequate in your circumstances
CELERYD_TASK_TIME_LIMIT = 5 * 60 CELERY_TASK_TIME_LIMIT = 5 * 60
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-soft-time-limit # http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-soft-time-limit
# TODO: set to whatever value is adequate in your circumstances # TODO: set to whatever value is adequate in your circumstances
CELERYD_TASK_SOFT_TIME_LIMIT = 60 CELERY_TASK_SOFT_TIME_LIMIT = 60
{%- endif %} {%- endif %}
# django-allauth # django-allauth

View File

@ -66,10 +66,12 @@ SECURE_CONTENT_TYPE_NOSNIFF = env.bool(
"DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True "DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True
) )
{% if cookiecutter.cloud_provider != 'None' -%}
# STORAGES # STORAGES
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# https://django-storages.readthedocs.io/en/latest/#installation # https://django-storages.readthedocs.io/en/latest/#installation
INSTALLED_APPS += ["storages"] # noqa F405 INSTALLED_APPS += ["storages"] # noqa F405
{%- endif -%}
{% if cookiecutter.cloud_provider == 'AWS' %} {% if cookiecutter.cloud_provider == 'AWS' %}
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings # https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID") AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID")
@ -93,19 +95,20 @@ AWS_S3_REGION_NAME = env("DJANGO_AWS_S3_REGION_NAME", default=None)
DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage" DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
GS_BUCKET_NAME = env("DJANGO_GCE_STORAGE_BUCKET_NAME") GS_BUCKET_NAME = env("DJANGO_GCE_STORAGE_BUCKET_NAME")
GS_DEFAULT_ACL = "publicRead" GS_DEFAULT_ACL = "publicRead"
{% endif %} {% endif -%}
{% if cookiecutter.cloud_provider != 'None' or cookiecutter.use_whitenoise == 'y' -%}
# STATIC # STATIC
# ------------------------ # ------------------------
{% endif -%}
{% if cookiecutter.use_whitenoise == 'y' -%} {% if cookiecutter.use_whitenoise == 'y' -%}
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
{%- endif -%} {% elif cookiecutter.cloud_provider == 'AWS' -%}
{%- if cookiecutter.cloud_provider == 'AWS' %}
STATICFILES_STORAGE = "config.settings.production.StaticRootS3Boto3Storage" STATICFILES_STORAGE = "config.settings.production.StaticRootS3Boto3Storage"
STATIC_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/static/" STATIC_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/static/"
{%- elif cookiecutter.cloud_provider == 'GCE' %} {% elif cookiecutter.cloud_provider == 'GCE' -%}
STATIC_URL = "https://storage.googleapis.com/{}/static/".format(GS_BUCKET_NAME) STATIC_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/static/"
{%- endif %} {% endif -%}
# MEDIA # MEDIA
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -117,6 +120,7 @@ from storages.backends.s3boto3 import S3Boto3Storage # noqa E402
class StaticRootS3Boto3Storage(S3Boto3Storage): class StaticRootS3Boto3Storage(S3Boto3Storage):
location = "static" location = "static"
default_acl = "public-read"
class MediaRootS3Boto3Storage(S3Boto3Storage): class MediaRootS3Boto3Storage(S3Boto3Storage):
@ -128,8 +132,8 @@ class MediaRootS3Boto3Storage(S3Boto3Storage):
DEFAULT_FILE_STORAGE = "config.settings.production.MediaRootS3Boto3Storage" DEFAULT_FILE_STORAGE = "config.settings.production.MediaRootS3Boto3Storage"
MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/" MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/"
{%- elif cookiecutter.cloud_provider == 'GCE' %} {%- elif cookiecutter.cloud_provider == 'GCE' %}
MEDIA_URL = "https://storage.googleapis.com/{}/media/".format(GS_BUCKET_NAME) MEDIA_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/"
MEDIA_ROOT = "https://storage.googleapis.com/{}/media/".format(GS_BUCKET_NAME) MEDIA_ROOT = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/"
{%- endif %} {%- endif %}
# TEMPLATES # TEMPLATES
@ -193,7 +197,7 @@ COMPRESS_ENABLED = env.bool("COMPRESS_ENABLED", default=True)
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_STORAGE # https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_STORAGE
COMPRESS_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" COMPRESS_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_URL # https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_URL
COMPRESS_URL = STATIC_URL{% if cookiecutter.use_whitenoise == 'y' %} # noqa F405{% endif %} COMPRESS_URL = STATIC_URL{% if cookiecutter.use_whitenoise == 'y' or cookiecutter.cloud_provider == 'None' %} # noqa F405{% endif %}
{% endif %} {% endif %}
{%- if cookiecutter.use_whitenoise == 'n' -%} {%- if cookiecutter.use_whitenoise == 'n' -%}
# Collectfast # Collectfast
@ -288,7 +292,7 @@ SENTRY_LOG_LEVEL = env.int("DJANGO_SENTRY_LOG_LEVEL", logging.INFO)
sentry_logging = LoggingIntegration( sentry_logging = LoggingIntegration(
level=SENTRY_LOG_LEVEL, # Capture info and above as breadcrumbs level=SENTRY_LOG_LEVEL, # Capture info and above as breadcrumbs
event_level=None, # Send no events from log messages event_level=logging.ERROR, # Send errors as events
) )
{%- if cookiecutter.use_celery == 'y' %} {%- if cookiecutter.use_celery == 'y' %}

View File

@ -45,7 +45,7 @@ services:
{%- if cookiecutter.use_celery == 'y' %} {%- if cookiecutter.use_celery == 'y' %}
redis: redis:
image: redis:3.2 image: redis:5.0
celeryworker: celeryworker:
<<: *django <<: *django

View File

@ -44,7 +44,7 @@ services:
- "0.0.0.0:443:443" - "0.0.0.0:443:443"
redis: redis:
image: redis:3.2 image: redis:5.0
{%- if cookiecutter.use_celery == 'y' %} {%- if cookiecutter.use_celery == 'y' %}
celeryworker: celeryworker:

View File

@ -1,10 +1,10 @@
-r ./base.txt -r ./base.txt
Werkzeug==0.15.4 # https://github.com/pallets/werkzeug Werkzeug==0.14.1 # pyup: < 0.15 # https://github.com/pallets/werkzeug
ipdb==0.12 # https://github.com/gotcha/ipdb ipdb==0.12 # https://github.com/gotcha/ipdb
Sphinx==2.0.1 # https://github.com/sphinx-doc/sphinx Sphinx==2.0.1 # https://github.com/sphinx-doc/sphinx
{%- if cookiecutter.use_docker == 'y' %} {%- if cookiecutter.use_docker == 'y' %}
psycopg2==2.8 --no-binary psycopg2 # https://github.com/psycopg/psycopg2 psycopg2==2.8.2 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
{%- else %} {%- else %}
psycopg2-binary==2.8.2 # https://github.com/psycopg/psycopg2 psycopg2-binary==2.8.2 # https://github.com/psycopg/psycopg2
{%- endif %} {%- endif %}
@ -17,7 +17,7 @@ pytest-sugar==0.9.2 # https://github.com/Frozenball/pytest-sugar
# Code quality # Code quality
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
flake8==3.7.5 # https://github.com/PyCQA/flake8 flake8==3.7.7 # https://github.com/PyCQA/flake8
coverage==4.5.3 # https://github.com/nedbat/coveragepy coverage==4.5.3 # https://github.com/nedbat/coveragepy
black==19.3b0 # https://github.com/ambv/black black==19.3b0 # https://github.com/ambv/black
pylint-django==2.0.9 # https://github.com/PyCQA/pylint-django pylint-django==2.0.9 # https://github.com/PyCQA/pylint-django
@ -30,6 +30,6 @@ pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery
factory-boy==2.12.0 # https://github.com/FactoryBoy/factory_boy factory-boy==2.12.0 # https://github.com/FactoryBoy/factory_boy
django-debug-toolbar==1.11 # https://github.com/jazzband/django-debug-toolbar django-debug-toolbar==1.11 # https://github.com/jazzband/django-debug-toolbar
django-extensions==2.1.6 # https://github.com/django-extensions/django-extensions django-extensions==2.1.7 # https://github.com/django-extensions/django-extensions
django-coverage-plugin==1.6.0 # https://github.com/nedbat/django_coverage_plugin django-coverage-plugin==1.6.0 # https://github.com/nedbat/django_coverage_plugin
pytest-django==3.4.8 # https://github.com/pytest-dev/pytest-django pytest-django==3.4.8 # https://github.com/pytest-dev/pytest-django

View File

@ -3,12 +3,12 @@
-r ./base.txt -r ./base.txt
gunicorn==19.9.0 # https://github.com/benoitc/gunicorn gunicorn==19.9.0 # https://github.com/benoitc/gunicorn
psycopg2==2.8 --no-binary psycopg2 # https://github.com/psycopg/psycopg2 psycopg2==2.8.2 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
{%- if cookiecutter.use_whitenoise == 'n' %} {%- if cookiecutter.use_whitenoise == 'n' %}
Collectfast==0.6.2 # https://github.com/antonagestam/collectfast Collectfast==0.6.2 # https://github.com/antonagestam/collectfast
{%- endif %} {%- endif %}
{%- if cookiecutter.use_sentry == "y" %} {%- if cookiecutter.use_sentry == "y" %}
sentry-sdk==0.7.14 # https://github.com/getsentry/sentry-python sentry-sdk==0.8.0 # https://github.com/getsentry/sentry-python
{%- endif %} {%- endif %}
# Django # Django
@ -18,4 +18,4 @@ django-storages[boto3]==1.7.1 # https://github.com/jschneier/django-storages
{%- elif cookiecutter.cloud_provider == 'GCE' %} {%- elif cookiecutter.cloud_provider == 'GCE' %}
django-storages[google]==1.7.1 # https://github.com/jschneier/django-storages django-storages[google]==1.7.1 # https://github.com/jschneier/django-storages
{%- endif %} {%- endif %}
django-anymail[mailgun]==6.0 # https://github.com/anymail/django-anymail django-anymail[mailgun]==6.0.1 # https://github.com/anymail/django-anymail

View File

@ -13,11 +13,6 @@ def test_detail(user: settings.AUTH_USER_MODEL):
assert resolve(f"/users/{user.username}/").view_name == "users:detail" assert resolve(f"/users/{user.username}/").view_name == "users:detail"
def test_list():
assert reverse("users:list") == "/users/"
assert resolve("/users/").view_name == "users:list"
def test_update(): def test_update():
assert reverse("users:update") == "/users/~update/" assert reverse("users:update") == "/users/~update/"
assert resolve("/users/~update/").view_name == "users:update" assert resolve("/users/~update/").view_name == "users:update"

View File

@ -1,7 +1,6 @@
from django.urls import path from django.urls import path
from {{ cookiecutter.project_slug }}.users.views import ( from {{ cookiecutter.project_slug }}.users.views import (
user_list_view,
user_redirect_view, user_redirect_view,
user_update_view, user_update_view,
user_detail_view, user_detail_view,
@ -9,7 +8,6 @@ from {{ cookiecutter.project_slug }}.users.views import (
app_name = "users" app_name = "users"
urlpatterns = [ urlpatterns = [
path("", view=user_list_view, name="list"),
path("~redirect/", view=user_redirect_view, name="redirect"), path("~redirect/", view=user_redirect_view, name="redirect"),
path("~update/", view=user_update_view, name="update"), path("~update/", view=user_update_view, name="update"),
path("<str:username>/", view=user_detail_view, name="detail"), path("<str:username>/", view=user_detail_view, name="detail"),

View File

@ -1,7 +1,7 @@
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse from django.urls import reverse
from django.views.generic import DetailView, ListView, RedirectView, UpdateView from django.views.generic import DetailView, RedirectView, UpdateView
User = get_user_model() User = get_user_model()
@ -16,16 +16,6 @@ class UserDetailView(LoginRequiredMixin, DetailView):
user_detail_view = UserDetailView.as_view() user_detail_view = UserDetailView.as_view()
class UserListView(LoginRequiredMixin, ListView):
model = User
slug_field = "username"
slug_url_kwarg = "username"
user_list_view = UserListView.as_view()
class UserUpdateView(LoginRequiredMixin, UpdateView): class UserUpdateView(LoginRequiredMixin, UpdateView):
model = User model = User