Merge branch 'master' into ci

This commit is contained in:
Andrew Chen Wang 2020-04-14 11:55:01 -04:00 committed by GitHub
commit 9e007699c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 141 additions and 104 deletions

View File

@ -5,7 +5,7 @@ services:
language: python language: python
python: 3.7 python: 3.8
before_install: before_install:
- docker-compose -v - docker-compose -v
@ -14,7 +14,7 @@ before_install:
matrix: matrix:
include: include:
- name: Test results - name: Test results
script: tox -e py37 script: tox -e py38
- name: Black template - name: Black template
script: tox -e black-template script: tox -e black-template
- name: Basic Docker - name: Basic Docker

View File

@ -1,6 +1,36 @@
# Change Log # Change Log
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.
## [2020-04-13]
### Changed
- Updated to Python 3.8 (@codnee)
- Moved converage config in setup.cfg (@danihodovic)
## [2020-04-08]
### Fixed
- Internal IPs for debug toolbar (@dudanogueira)
## [2020-04-04]
### Fixed
- Added compress command command with Django compressor (@gwiskur)
## [2020-03-23]
### Changed
- Updated project to Django 3.0
## [2020-03-17]
### Changed
- Handle paths using Pathlib (@jules-ch)
### Fixed
- Pre-commit hook regex (@demestav)
## [2020-03-16]
### Added
- Support for all Anymail providers (@Andrew-Chen-Wang)
### Fixed
- Django compressor setup (@jameswilliams1)
## [2020-01-23] ## [2020-01-23]
### Changed ### Changed
- Fix UserFactory to set the password if provided (@BoPeng) - Fix UserFactory to set the password if provided (@BoPeng)

View File

@ -39,9 +39,9 @@ To run all tests using various versions of python in virtualenvs defined in tox.
It is possible to test with a specific version of python. To do this, the command It is possible to test with a specific version of python. To do this, the command
is:: is::
$ tox -e py37 $ tox -e py38
This will run py.test with the python3.7 interpreter, for example. This will run py.test with the python3.8 interpreter, for example.
To run a particular test with tox for against your current Python version:: To run a particular test with tox for against your current Python version::

View File

@ -112,15 +112,19 @@ Listed in alphabetical order.
Diane Chen `@purplediane`_ @purplediane88 Diane Chen `@purplediane`_ @purplediane88
Dónal Adams `@epileptic-fish`_ Dónal Adams `@epileptic-fish`_
Dong Huynh `@trungdong`_ Dong Huynh `@trungdong`_
Duda Nogueira `@dudanogueira`_ @dudanogueira
Emanuel Calso `@bloodpet`_ @bloodpet Emanuel Calso `@bloodpet`_ @bloodpet
Eraldo Energy `@eraldo`_ Eraldo Energy `@eraldo`_
Eric Groom `@ericgroom`_ Eric Groom `@ericgroom`_
Ernesto Cedeno `@codnee`_
Eyad Al Sibai `@eyadsibai`_ Eyad Al Sibai `@eyadsibai`_
Felipe Arruda `@arruda`_ Felipe Arruda `@arruda`_
Florian Idelberger `@step21`_ @windrush Florian Idelberger `@step21`_ @windrush
Gabriel Mejia `@elgartoinf`_ @elgartoinf
Garry Cairns `@garry-cairns`_ Garry Cairns `@garry-cairns`_
Garry Polley `@garrypolley`_ Garry Polley `@garrypolley`_
Gilbishkosma `@Gilbishkosma`_ Gilbishkosma `@Gilbishkosma`_
Glenn Wiskur `@gwiskur`_
Guilherme Guy `@guilherme1guy`_ Guilherme Guy `@guilherme1guy`_
Hamish Durkin `@durkode`_ Hamish Durkin `@durkode`_
Hana Quadara `@hanaquadara`_ Hana Quadara `@hanaquadara`_
@ -268,6 +272,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
.. _@cmargieson: https://github.com/cmargieson .. _@cmargieson: https://github.com/cmargieson
.. _@codnee: https://github.com/codnee
.. _@cole: https://github.com/cole .. _@cole: https://github.com/cole
.. _@Collederas: https://github.com/Collederas .. _@Collederas: https://github.com/Collederas
.. _@curtisstpierre: https://github.com/curtisstpierre .. _@curtisstpierre: https://github.com/curtisstpierre
@ -281,10 +286,12 @@ Listed in alphabetical order.
.. _@dezoito: https://github.com/dezoito .. _@dezoito: https://github.com/dezoito
.. _@dhepper: https://github.com/dhepper .. _@dhepper: https://github.com/dhepper
.. _@dot2dotseurat: https://github.com/dot2dotseurat .. _@dot2dotseurat: https://github.com/dot2dotseurat
.. _@dudanogueira: https://github.com/dudanogueira
.. _@dsclementsen: https://github.com/dsclementsen .. _@dsclementsen: https://github.com/dsclementsen
.. _@guilherme1guy: https://github.com/guilherme1guy .. _@guilherme1guy: https://github.com/guilherme1guy
.. _@durkode: https://github.com/durkode .. _@durkode: https://github.com/durkode
.. _@Egregors: https://github.com/Egregors .. _@Egregors: https://github.com/Egregors
.. _@elgartoinf: https://gihub.com/elgartoinf
.. _@epileptic-fish: https://gihub.com/epileptic-fish .. _@epileptic-fish: https://gihub.com/epileptic-fish
.. _@eraldo: https://github.com/eraldo .. _@eraldo: https://github.com/eraldo
.. _@erfaan: https://github.com/erfaan .. _@erfaan: https://github.com/erfaan
@ -296,6 +303,7 @@ Listed in alphabetical order.
.. _@garry-cairns: https://github.com/garry-cairns .. _@garry-cairns: https://github.com/garry-cairns
.. _@garrypolley: https://github.com/garrypolley .. _@garrypolley: https://github.com/garrypolley
.. _@Gilbishkosma: https://github.com/Gilbishkosma .. _@Gilbishkosma: https://github.com/Gilbishkosma
.. _@gwiskur: https://github.com/gwiskur
.. _@glasslion: https://github.com/glasslion .. _@glasslion: https://github.com/glasslion
.. _@goldhand: https://github.com/goldhand .. _@goldhand: https://github.com/goldhand
.. _@hackebrot: https://github.com/hackebrot .. _@hackebrot: https://github.com/hackebrot

View File

@ -1,4 +1,4 @@
Copyright (c) 2013-2018, Daniel Roy Greenfeld Copyright (c) 2013-2020, Daniel Roy Greenfeld
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,

View File

@ -36,8 +36,8 @@ production-ready Django projects quickly.
Features Features
--------- ---------
* For Django 2.2 * For Django 3.0
* Works with Python 3.7 * Works with Python 3.8
* Renders Django projects with 100% starting test coverage * Renders Django projects with 100% starting test coverage
* Twitter Bootstrap_ v4 (`maintained Foundation fork`_ also available) * Twitter Bootstrap_ v4 (`maintained Foundation fork`_ also available)
* 12-Factor_ based settings via django-environ_ * 12-Factor_ based settings via django-environ_
@ -272,7 +272,7 @@ If you do rename your fork, I encourage you to submit it to the following places
* cookiecutter_ so it gets listed in the README as a template. * cookiecutter_ so it gets listed in the README as a template.
* The cookiecutter grid_ on Django Packages. * The cookiecutter grid_ on Django Packages.
.. _cookiecutter: https://github.com/audreyr/cookiecutter .. _cookiecutter: https://github.com/cookiecutter/cookiecutter
.. _grid: https://www.djangopackages.com/grids/g/cookiecutters/ .. _grid: https://www.djangopackages.com/grids/g/cookiecutters/
Submit a Pull Request Submit a Pull Request

View File

@ -15,7 +15,7 @@ Full instructions follow, but here's a high-level view.
2. Set your config variables in the *postactivate* script 2. Set your config variables in the *postactivate* script
3. Run the *manage.py* ``migrate`` and ``collectstatic`` commands 3. Run the *manage.py* ``migrate`` and ``collectstatic`` {%- if cookiecutter.use_compressor == "y" %}and ``compress`` {%- endif %}commands
4. Add an entry to the PythonAnywhere *Web tab* 4. Add an entry to the PythonAnywhere *Web tab*
@ -35,7 +35,7 @@ Make sure your project is fully committed and pushed up to Bitbucket or Github o
git clone <my-repo-url> # you can also use hg git clone <my-repo-url> # you can also use hg
cd my-project-name cd my-project-name
mkvirtualenv --python=/usr/bin/python3.7 my-project-name mkvirtualenv --python=/usr/bin/python3.8 my-project-name
pip install -r requirements/production.txt # may take a few minutes pip install -r requirements/production.txt # may take a few minutes
@ -109,6 +109,7 @@ Now run the migration, and collectstatic:
source $VIRTUAL_ENV/bin/postactivate source $VIRTUAL_ENV/bin/postactivate
python manage.py migrate python manage.py migrate
python manage.py collectstatic python manage.py collectstatic
{%- if cookiecutter.use_compressor == "y" %}python manage.py compress {%- endif %}
# and, optionally # and, optionally
python manage.py createsuperuser python manage.py createsuperuser
@ -175,6 +176,7 @@ For subsequent deployments, the procedure is much simpler. In a Bash console:
git pull git pull
python manage.py migrate python manage.py migrate
python manage.py collectstatic python manage.py collectstatic
{%- if cookiecutter.use_compressor == "y" %}python manage.py compress {%- endif %}
And then go to the Web tab and hit **Reload** And then go to the Web tab and hit **Reload**

View File

@ -9,7 +9,7 @@ Setting Up Development Environment
Make sure to have the following on your host: Make sure to have the following on your host:
* Python 3.7 * Python 3.8
* PostgreSQL_. * PostgreSQL_.
* Redis_, if using Celery * Redis_, if using Celery
@ -17,7 +17,7 @@ First things first.
#. Create a virtualenv: :: #. Create a virtualenv: ::
$ python3.7 -m venv <virtual env path> $ python3.8 -m venv <virtual env path>
#. Activate the virtualenv you have just created: :: #. Activate the virtualenv you have just created: ::

View File

@ -24,4 +24,4 @@ Why doesn't this follow the layout from Two Scoops of Django?
You may notice that some elements of this project do not exactly match what we describe in chapter 3 of `Two Scoops of Django 1.11`_. The reason for that is this project, amongst other things, serves as a test bed for trying out new ideas and concepts. Sometimes they work, sometimes they don't, but the end result is that it won't necessarily match precisely what is described in the book I co-authored. You may notice that some elements of this project do not exactly match what we describe in chapter 3 of `Two Scoops of Django 1.11`_. The reason for that is this project, amongst other things, serves as a test bed for trying out new ideas and concepts. Sometimes they work, sometimes they don't, but the end result is that it won't necessarily match precisely what is described in the book I co-authored.
.. _Two Scoops of Django 1.11: https://www.twoscoopspress.com/collections/django/products/two-scoops-of-django-1-11 .. _Two Scoops of Django 1.11: https://www.feldroy.com/collections/django/products/two-scoops-of-django-1-11

View File

@ -5,7 +5,7 @@ Welcome to Cookiecutter Django's documentation!
A Cookiecutter_ template for Django. A Cookiecutter_ template for Django.
.. _cookiecutter: https://github.com/audreyr/cookiecutter .. _cookiecutter: https://github.com/cookiecutter/cookiecutter
Contents: Contents:

View File

@ -292,6 +292,10 @@ def remove_drf_starter_files():
shutil.rmtree(os.path.join("{{cookiecutter.project_slug}}", "users", "api")) shutil.rmtree(os.path.join("{{cookiecutter.project_slug}}", "users", "api"))
def remove_storages_module():
os.remove(os.path.join("{{cookiecutter.project_slug}}", "utils", "storages.py"))
def main(): def main():
debug = "{{ cookiecutter.debug }}".lower() == "y" debug = "{{ cookiecutter.debug }}".lower() == "y"
@ -352,6 +356,7 @@ def main():
WARNING + "You chose not to use a cloud provider, " WARNING + "You chose not to use a cloud provider, "
"media files won't be served in production." + TERMINATOR "media files won't be served in production." + TERMINATOR
) )
remove_storages_module()
if "{{ cookiecutter.use_celery }}".lower() == "n": if "{{ cookiecutter.use_celery }}".lower() == "n":
remove_celery_files() remove_celery_files()

View File

@ -35,7 +35,7 @@ if "{{ cookiecutter.use_docker }}".lower() == "n":
if python_major_version == 2: if python_major_version == 2:
print( print(
WARNING + "You're running cookiecutter under Python 2, but the generated " WARNING + "You're running cookiecutter under Python 2, but the generated "
"project requires Python 3.7+. Do you want to proceed (y/n)? " + TERMINATOR "project requires Python 3.8+. Do you want to proceed (y/n)? " + TERMINATOR
) )
yes_options, no_options = frozenset(["y"]), frozenset(["n"]) yes_options, no_options = frozenset(["y"]), frozenset(["n"])
while True: while True:

View File

@ -6,11 +6,11 @@ binaryornot==0.4.4
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
black==19.10b0 black==19.10b0
flake8==3.7.9 flake8==3.7.9
flake8-isort==2.9.0 flake8-isort==2.9.1
# Testing # Testing
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
tox==3.14.5 tox==3.14.6
pytest==5.4.1 pytest==5.4.1
pytest-cookies==0.5.1 pytest-cookies==0.5.1
pytest-instafail==0.4.1.post0 pytest-instafail==0.4.1.post0

View File

@ -10,7 +10,7 @@ except ImportError:
# Our version ALWAYS matches the version of Django we support # 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. # If Django has a new release, we branch, tag, then update this setting after the tag.
version = "2.2.1" version = "3.0.5"
if sys.argv[-1] == "tag": if sys.argv[-1] == "tag":
os.system(f'git tag -a {version} -m "version {version}"') os.system(f'git tag -a {version} -m "version {version}"')
@ -34,13 +34,13 @@ setup(
classifiers=[ classifiers=[
"Development Status :: 4 - Beta", "Development Status :: 4 - Beta",
"Environment :: Console", "Environment :: Console",
"Framework :: Django :: 2.2", "Framework :: Django :: 3.0",
"Intended Audience :: Developers", "Intended Audience :: Developers",
"Natural Language :: English", "Natural Language :: English",
"License :: OSI Approved :: BSD License", "License :: OSI Approved :: BSD License",
"Programming Language :: Python", "Programming Language :: Python",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: CPython",
"Topic :: Software Development", "Topic :: Software Development",
], ],

View File

@ -1,6 +1,6 @@
[tox] [tox]
skipsdist = true skipsdist = true
envlist = py37,black-template envlist = py38,black-template
[testenv] [testenv]
deps = -rrequirements.txt deps = -rrequirements.txt

View File

@ -1,5 +0,0 @@
[run]
include = {{cookiecutter.project_slug}}/*
omit = *migrations*, *tests*
plugins =
django_coverage_plugin

View File

@ -7,6 +7,9 @@ variables:
POSTGRES_PASSWORD: '' POSTGRES_PASSWORD: ''
POSTGRES_DB: 'test_{{ cookiecutter.project_slug }}' POSTGRES_DB: 'test_{{ cookiecutter.project_slug }}'
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
{% if cookiecutter.use_celery == 'y' -%}
CELERY_BROKER_URL: 'redis://redis:6379/0'
{%- endif %}
flake8: flake8:
stage: lint stage: lint

View File

@ -2,7 +2,7 @@ dist: xenial
language: python language: python
python: python:
- "3.7" - "3.8"
services: services:
- {% if cookiecutter.use_docker == 'y' %}docker{% else %}postgresql{% endif %} - {% if cookiecutter.use_docker == 'y' %}docker{% else %}postgresql{% endif %}

View File

@ -1,4 +1,4 @@
FROM python:3.7-slim-buster FROM python:3.8-slim-buster
ENV PYTHONUNBUFFERED 1 ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONDONTWRITEBYTECODE 1

View File

@ -9,7 +9,7 @@ RUN npm run build
# Python build stage # Python build stage
{%- endif %} {%- endif %}
FROM python:3.7-slim-buster FROM python:3.8-slim-buster
ENV PYTHONUNBUFFERED 1 ENV PYTHONUNBUFFERED 1

View File

@ -228,7 +228,7 @@ X_FRAME_OPTIONS = "DENY"
EMAIL_BACKEND = env( EMAIL_BACKEND = env(
"DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.smtp.EmailBackend" "DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.smtp.EmailBackend"
) )
# https://docs.djangoproject.com/en/2.2/ref/settings/#email-timeout # https://docs.djangoproject.com/en/dev/ref/settings/#email-timeout
EMAIL_TIMEOUT = 5 EMAIL_TIMEOUT = 5
# ADMIN # ADMIN
@ -311,7 +311,7 @@ INSTALLED_APPS += ["compressor"]
STATICFILES_FINDERS += ["compressor.finders.CompressorFinder"] STATICFILES_FINDERS += ["compressor.finders.CompressorFinder"]
{%- endif %} {%- endif %}
{% if cookiecutter.use_drf == "y" -%} {% if cookiecutter.use_drf == "y" -%}
# django-reset-framework # django-rest-framework
# ------------------------------------------------------------------------------- # -------------------------------------------------------------------------------
# django-rest-framework - https://www.django-rest-framework.org/api-guide/settings/ # django-rest-framework - https://www.django-rest-framework.org/api-guide/settings/
REST_FRAMEWORK = { REST_FRAMEWORK = {

View File

@ -68,7 +68,7 @@ if env("USE_DOCKER") == "yes":
import socket import socket
hostname, _, ips = socket.gethostbyname_ex(socket.gethostname()) hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
INTERNAL_IPS += [ip[:-1] + "1" for ip in ips] INTERNAL_IPS += [".".join(ip.split(".")[:-1] + ["1"]) for ip in ips]
{%- endif %} {%- endif %}
# django-extensions # django-extensions

View File

@ -1,9 +1,7 @@
"""isort:skip_file"""
{% if cookiecutter.use_sentry == 'y' -%} {% if cookiecutter.use_sentry == 'y' -%}
import logging import logging
import sentry_sdk import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.logging import LoggingIntegration from sentry_sdk.integrations.logging import LoggingIntegration
{%- if cookiecutter.use_celery == 'y' %} {%- if cookiecutter.use_celery == 'y' %}
@ -104,11 +102,11 @@ GS_DEFAULT_ACL = "publicRead"
{% if cookiecutter.use_whitenoise == 'y' -%} {% if cookiecutter.use_whitenoise == 'y' -%}
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
{% elif cookiecutter.cloud_provider == 'AWS' -%} {% elif cookiecutter.cloud_provider == 'AWS' -%}
STATICFILES_STORAGE = "config.settings.production.StaticRootS3Boto3Storage" STATICFILES_STORAGE = "{{cookiecutter.project_slug}}.utils.storages.StaticRootS3Boto3Storage"
COLLECTFAST_STRATEGY = "collectfast.strategies.boto3.Boto3Strategy" COLLECTFAST_STRATEGY = "collectfast.strategies.boto3.Boto3Strategy"
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 == 'GCP' -%} {% elif cookiecutter.cloud_provider == 'GCP' -%}
STATICFILES_STORAGE = "config.settings.production.StaticRootGoogleCloudStorage" STATICFILES_STORAGE = "{{cookiecutter.project_slug}}.utils.storages.StaticRootGoogleCloudStorage"
COLLECTFAST_STRATEGY = "collectfast.strategies.gcloud.GoogleCloudStrategy" COLLECTFAST_STRATEGY = "collectfast.strategies.gcloud.GoogleCloudStrategy"
STATIC_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/static/" STATIC_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/static/"
{% endif -%} {% endif -%}
@ -116,39 +114,10 @@ STATIC_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/static/"
# MEDIA # MEDIA
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
{%- if cookiecutter.cloud_provider == 'AWS' %} {%- if cookiecutter.cloud_provider == 'AWS' %}
# region http://stackoverflow.com/questions/10390244/ DEFAULT_FILE_STORAGE = "{{cookiecutter.project_slug}}.utils.storages.MediaRootS3Boto3Storage"
# Full-fledge class: https://stackoverflow.com/a/18046120/104731
from storages.backends.s3boto3 import S3Boto3Storage # noqa E402
class StaticRootS3Boto3Storage(S3Boto3Storage):
location = "static"
default_acl = "public-read"
class MediaRootS3Boto3Storage(S3Boto3Storage):
location = "media"
file_overwrite = False
# endregion
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 == 'GCP' %} {%- elif cookiecutter.cloud_provider == 'GCP' %}
from storages.backends.gcloud import GoogleCloudStorage # noqa E402 DEFAULT_FILE_STORAGE = "{{cookiecutter.project_slug}}.utils.storages.MediaRootGoogleCloudStorage"
class StaticRootGoogleCloudStorage(GoogleCloudStorage):
location = "static"
default_acl = "publicRead"
class MediaRootGoogleCloudStorage(GoogleCloudStorage):
location = "media"
file_overwrite = False
DEFAULT_FILE_STORAGE = "config.settings.production.MediaRootGoogleCloudStorage"
MEDIA_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/" MEDIA_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/"
{%- endif %} {%- endif %}

View File

@ -14,7 +14,7 @@ This repository comes with already prepared "Run/Debug Configurations" for docke
.. image:: images/2.png .. image:: images/2.png
But as you can see, at the beginning there is something wrong with them. They have red X on django icon, and they cannot be used, without configuring remote python interpteter. To do that, you have to go to *Settings > Build, Execution, Deployment* first. But as you can see, at the beginning there is something wrong with them. They have red X on django icon, and they cannot be used, without configuring remote python interpreter. To do that, you have to go to *Settings > Build, Execution, Deployment* first.
Next, you have to add new remote python interpreter, based on already tested deployment settings. Go to *Settings > Project > Project Interpreter*. Click on the cog icon, and click *Add Remote*. Next, you have to add new remote python interpreter, based on already tested deployment settings. Go to *Settings > Project > Project Interpreter*. Click on the cog icon, and click *Add Remote*.

View File

@ -1,6 +1,6 @@
pytz==2019.3 # https://github.com/stub42/pytz pytz==2019.3 # https://github.com/stub42/pytz
python-slugify==4.0.0 # https://github.com/un33k/python-slugify python-slugify==4.0.0 # https://github.com/un33k/python-slugify
Pillow==7.0.0 # https://github.com/python-pillow/Pillow Pillow==7.1.1 # https://github.com/python-pillow/Pillow
{%- if cookiecutter.use_compressor == "y" %} {%- 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 rcssmin==1.0.6{% if cookiecutter.windows == 'y' and cookiecutter.use_docker == 'n' %} --install-option="--without-c-extensions"{% endif %} # https://github.com/ndparker/rcssmin
{%- endif %} {%- endif %}
@ -13,13 +13,13 @@ redis==3.4.1 # https://github.com/andymccurdy/redis-py
celery==4.4.2 # pyup: < 5.0 # https://github.com/celery/celery celery==4.4.2 # pyup: < 5.0 # https://github.com/celery/celery
django-celery-beat==2.0.0 # https://github.com/celery/django-celery-beat django-celery-beat==2.0.0 # https://github.com/celery/django-celery-beat
{%- if cookiecutter.use_docker == 'y' %} {%- if cookiecutter.use_docker == 'y' %}
flower==0.9.3 # https://github.com/mher/flower flower==0.9.4 # https://github.com/mher/flower
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
# Django # Django
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
django==2.2.11 # pyup: < 3.0 # https://www.djangoproject.com/ django==3.0.5 # pyup: < 3.1 # https://www.djangoproject.com/
django-environ==0.4.5 # https://github.com/joke2k/django-environ 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-model-utils==4.0.0 # https://github.com/jazzband/django-model-utils
django-allauth==0.41.0 # https://github.com/pennersr/django-allauth django-allauth==0.41.0 # https://github.com/pennersr/django-allauth

View File

@ -1,12 +1,12 @@
-r ./base.txt -r ./base.txt
Werkzeug==1.0.0 # https://github.com/pallets/werkzeug Werkzeug==1.0.1 # https://github.com/pallets/werkzeug
ipdb==0.13.2 # https://github.com/gotcha/ipdb ipdb==0.13.2 # https://github.com/gotcha/ipdb
Sphinx==2.4.4 # https://github.com/sphinx-doc/sphinx Sphinx==3.0.1 # https://github.com/sphinx-doc/sphinx
{%- if cookiecutter.use_docker == 'y' %} {%- if cookiecutter.use_docker == 'y' %}
psycopg2==2.8.4 --no-binary psycopg2 # https://github.com/psycopg/psycopg2 psycopg2==2.8.5 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
{%- else %} {%- else %}
psycopg2-binary==2.8.4 # https://github.com/psycopg/psycopg2 psycopg2-binary==2.8.5 # https://github.com/psycopg/psycopg2
{%- endif %} {%- endif %}
# Testing # Testing
@ -19,10 +19,10 @@ pytest-sugar==0.9.2 # https://github.com/Frozenball/pytest-sugar
# Code quality # Code quality
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
flake8==3.7.9 # https://github.com/PyCQA/flake8 flake8==3.7.9 # https://github.com/PyCQA/flake8
flake8-isort==2.9.0 # https://github.com/gforcada/flake8-isort flake8-isort==2.9.1 # https://github.com/gforcada/flake8-isort
coverage==5.0.4 # https://github.com/nedbat/coveragepy coverage==5.1 # https://github.com/nedbat/coveragepy
black==19.10b0 # https://github.com/ambv/black black==19.10b0 # https://github.com/ambv/black
pylint-django==2.0.14 # https://github.com/PyCQA/pylint-django pylint-django==2.0.15 # https://github.com/PyCQA/pylint-django
{%- if cookiecutter.use_celery == 'y' %} {%- if cookiecutter.use_celery == 'y' %}
pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery pylint-celery==0.3 # https://github.com/PyCQA/pylint-celery
{%- endif %} {%- endif %}
@ -33,6 +33,6 @@ pre-commit==2.2.0 # https://github.com/pre-commit/pre-commit
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==2.2 # https://github.com/jazzband/django-debug-toolbar django-debug-toolbar==2.2 # https://github.com/jazzband/django-debug-toolbar
django-extensions==2.2.8 # https://github.com/django-extensions/django-extensions django-extensions==2.2.9 # https://github.com/django-extensions/django-extensions
django-coverage-plugin==1.8.0 # https://github.com/nedbat/django_coverage_plugin django-coverage-plugin==1.8.0 # https://github.com/nedbat/django_coverage_plugin
pytest-django==3.8.0 # https://github.com/pytest-dev/pytest-django pytest-django==3.9.0 # https://github.com/pytest-dev/pytest-django

View File

@ -3,7 +3,7 @@
-r ./base.txt -r ./base.txt
gunicorn==20.0.4 # https://github.com/benoitc/gunicorn gunicorn==20.0.4 # https://github.com/benoitc/gunicorn
psycopg2==2.8.4 --no-binary psycopg2 # https://github.com/psycopg/psycopg2 psycopg2==2.8.5 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
{%- if cookiecutter.use_whitenoise == 'n' %} {%- if cookiecutter.use_whitenoise == 'n' %}
Collectfast==2.1.0 # https://github.com/antonagestam/collectfast Collectfast==2.1.0 # https://github.com/antonagestam/collectfast
{%- endif %} {%- endif %}
@ -19,21 +19,21 @@ django-storages[boto3]==1.9.1 # https://github.com/jschneier/django-storages
django-storages[google]==1.9.1 # https://github.com/jschneier/django-storages django-storages[google]==1.9.1 # https://github.com/jschneier/django-storages
{%- endif %} {%- endif %}
{%- if cookiecutter.mail_service == 'Mailgun' %} {%- if cookiecutter.mail_service == 'Mailgun' %}
django-anymail[mailgun]==7.0.0 # https://github.com/anymail/django-anymail django-anymail[mailgun]==7.1.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Amazon SES' %} {%- elif cookiecutter.mail_service == 'Amazon SES' %}
django-anymail[amazon_ses]==7.0.0 # https://github.com/anymail/django-anymail django-anymail[amazon_ses]==7.1.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Mailjet' %} {%- elif cookiecutter.mail_service == 'Mailjet' %}
django-anymail[mailjet]==7.0.0 # https://github.com/anymail/django-anymail django-anymail[mailjet]==7.1.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Mandrill' %} {%- elif cookiecutter.mail_service == 'Mandrill' %}
django-anymail[mandrill]==7.0.0 # https://github.com/anymail/django-anymail django-anymail[mandrill]==7.1.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Postmark' %} {%- elif cookiecutter.mail_service == 'Postmark' %}
django-anymail[postmark]==7.0.0 # https://github.com/anymail/django-anymail django-anymail[postmark]==7.1.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Sendgrid' %} {%- elif cookiecutter.mail_service == 'Sendgrid' %}
django-anymail[sendgrid]==7.0.0 # https://github.com/anymail/django-anymail django-anymail[sendgrid]==7.1.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'SendinBlue' %} {%- elif cookiecutter.mail_service == 'SendinBlue' %}
django-anymail[sendinblue]==7.0.0 # https://github.com/anymail/django-anymail django-anymail[sendinblue]==7.1.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'SparkPost' %} {%- elif cookiecutter.mail_service == 'SparkPost' %}
django-anymail[sparkpost]==7.0.0 # https://github.com/anymail/django-anymail django-anymail[sparkpost]==7.1.0 # https://github.com/anymail/django-anymail
{%- elif cookiecutter.mail_service == 'Other SMTP' %} {%- elif cookiecutter.mail_service == 'Other SMTP' %}
django-anymail==7.0.0 # https://github.com/anymail/django-anymail django-anymail==7.1.0 # https://github.com/anymail/django-anymail
{%- endif %} {%- endif %}

View File

@ -1 +1 @@
python-3.7.6 python-3.8.2

View File

@ -7,7 +7,7 @@ max-line-length = 120
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules
[mypy] [mypy]
python_version = 3.7 python_version = 3.8
check_untyped_defs = True check_untyped_defs = True
ignore_missing_imports = True ignore_missing_imports = True
warn_unused_ignores = True warn_unused_ignores = True
@ -21,3 +21,9 @@ django_settings_module = config.settings.test
[mypy-*.migrations.*] [mypy-*.migrations.*]
# Django migrations should not produce any errors: # Django migrations should not produce any errors:
ignore_errors = True ignore_errors = True
[coverage:run]
include = {{cookiecutter.project_slug}}/*
omit = *migrations*, *tests*
plugins =
django_coverage_plugin

View File

@ -1,5 +1,4 @@
import pytest import pytest
from django.test import RequestFactory
from {{ cookiecutter.project_slug }}.users.models import User from {{ cookiecutter.project_slug }}.users.models import User
from {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory from {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory
@ -13,8 +12,3 @@ def media_storage(settings, tmpdir):
@pytest.fixture @pytest.fixture
def user() -> User: def user() -> User:
return UserFactory() return UserFactory()
@pytest.fixture
def request_factory() -> RequestFactory:
return RequestFactory()

View File

@ -16,18 +16,18 @@ class TestUserUpdateView:
https://github.com/pytest-dev/pytest-django/pull/258 https://github.com/pytest-dev/pytest-django/pull/258
""" """
def test_get_success_url(self, user: User, request_factory: RequestFactory): def test_get_success_url(self, user: User, rf: RequestFactory):
view = UserUpdateView() view = UserUpdateView()
request = request_factory.get("/fake-url/") request = rf.get("/fake-url/")
request.user = user request.user = user
view.request = request view.request = request
assert view.get_success_url() == f"/users/{user.username}/" assert view.get_success_url() == f"/users/{user.username}/"
def test_get_object(self, user: User, request_factory: RequestFactory): def test_get_object(self, user: User, rf: RequestFactory):
view = UserUpdateView() view = UserUpdateView()
request = request_factory.get("/fake-url/") request = rf.get("/fake-url/")
request.user = user request.user = user
view.request = request view.request = request
@ -36,9 +36,9 @@ class TestUserUpdateView:
class TestUserRedirectView: class TestUserRedirectView:
def test_get_redirect_url(self, user: User, request_factory: RequestFactory): def test_get_redirect_url(self, user: User, rf: RequestFactory):
view = UserRedirectView() view = UserRedirectView()
request = request_factory.get("/fake-url") request = rf.get("/fake-url")
request.user = user request.user = user
view.request = request view.request = request

View File

@ -0,0 +1,25 @@
{% if cookiecutter.cloud_provider == 'AWS' -%}
from storages.backends.s3boto3 import S3Boto3Storage
class StaticRootS3Boto3Storage(S3Boto3Storage):
location = "static"
default_acl = "public-read"
class MediaRootS3Boto3Storage(S3Boto3Storage):
location = "media"
file_overwrite = False
{%- elif cookiecutter.cloud_provider == 'GCP' -%}
from storages.backends.gcloud import GoogleCloudStorage
class StaticRootGoogleCloudStorage(GoogleCloudStorage):
location = "static"
default_acl = "publicRead"
class MediaRootGoogleCloudStorage(GoogleCloudStorage):
location = "media"
file_overwrite = False
{%- endif %}