Removed some cookie cutter parameters:

- `use_heroku`,
- `keep_local_envs_in_vcs`,
- `windows`,
- `use_pycharm`,
- `use_docker`,
- `postgresql_version`,
- `js_task_runner`,
- `custom_bootstrsp_compilation`,
- `debug`
This commit is contained in:
Corey Oordt 2019-07-22 13:36:23 -05:00
parent d82904aafe
commit b48eb3670b
32 changed files with 292 additions and 740 deletions

View File

@ -163,28 +163,12 @@ Answer the prompts with your own desired options_. For example::
use_celery [n]: y use_celery [n]: y
use_mailhog [n]: n use_mailhog [n]: n
use_sentry [n]: y use_sentry [n]: y
use_pycharm [n]: y
windows [n]: n
use_docker [n]: n
use_heroku [n]: y
use_compressor [n]: y use_compressor [n]: y
Select postgresql_version:
1 - 11.3
2 - 10.8
3 - 9.6
4 - 9.5
5 - 9.4
Choose from 1, 2, 3, 4, 5 [1]: 1
Select js_task_runner:
1 - None
2 - Gulp
Choose from 1, 2 [1]: 1
Select cloud_provider: Select cloud_provider:
1 - AWS 1 - AWS
2 - GCP 2 - GCP
3 - None 3 - None
Choose from 1, 2, 3 [1]: 1 Choose from 1, 2, 3 [1]: 1
custom_bootstrap_compilation [n]: n
Select open_source_license: Select open_source_license:
1 - MIT 1 - MIT
2 - BSD 2 - BSD
@ -192,8 +176,6 @@ Answer the prompts with your own desired options_. For example::
4 - Apache Software License 2.0 4 - Apache Software License 2.0
5 - Not open source 5 - Not open source
Choose from 1, 2, 3, 4, 5 [1]: 1 Choose from 1, 2, 3, 4, 5 [1]: 1
keep_local_envs_in_vcs [y]: y
debug[n]: n
Enter the project and take a look around:: Enter the project and take a look around::

View File

@ -2,7 +2,7 @@
"project_name": "My Awesome Project", "project_name": "My Awesome Project",
"project_slug": "{{ cookiecutter.project_name.lower()|replace(' ', '_')|replace('-', '_')|replace('.', '_')|trim() }}", "project_slug": "{{ cookiecutter.project_name.lower()|replace(' ', '_')|replace('-', '_')|replace('.', '_')|trim() }}",
"description": "Behold My Awesome Project!", "description": "Behold My Awesome Project!",
"author_name": "Daniel Roy Greenfeld", "author_name": "Your Name",
"domain_name": "example.com", "domain_name": "example.com",
"email": "{{ cookiecutter.author_name.lower()|replace(' ', '-') }}@example.com", "email": "{{ cookiecutter.author_name.lower()|replace(' ', '-') }}@example.com",
"version": "0.1.0", "version": "0.1.0",
@ -14,34 +14,16 @@
"Not open source" "Not open source"
], ],
"timezone": "UTC", "timezone": "UTC",
"windows": "n",
"use_pycharm": "n",
"use_docker": "n",
"postgresql_version": [
"11.3",
"10.8",
"9.6",
"9.5",
"9.4"
],
"js_task_runner": [
"None",
"Gulp"
],
"cloud_provider": [ "cloud_provider": [
"AWS", "AWS",
"Azure",
"GCP", "GCP",
"None" "None"
], ],
"custom_bootstrap_compilation": "n",
"use_compressor": "n", "use_compressor": "n",
"use_celery": "n", "use_celery": "n",
"use_mailhog": "n", "use_mailhog": "n",
"use_sentry": "n", "use_sentry": "n",
"use_whitenoise": "n", "use_whitenoise": "n",
"use_heroku": "n", "use_travisci": "n"
"use_travisci": "n",
"keep_local_envs_in_vcs": "y",
"debug": "n"
} }

View File

@ -37,29 +37,6 @@ open_source_license:
timezone: timezone:
The value to be used for the ``TIME_ZONE`` setting of the project. The value to be used for the ``TIME_ZONE`` setting of the project.
windows:
Indicates whether the project should be configured for development on Windows.
use_pycharm:
Indicates whether the project should be configured for development with PyCharm_.
use_docker:
Indicates whether the project should be configured to use Docker_ and `Docker Compose`_.
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
js_task_runner:
Select a JavaScript task runner. The choices are:
1. None
2. Gulp_
cloud_provider: cloud_provider:
Select a cloud provider for static & media files. The choices are: Select a cloud provider for static & media files. The choices are:
@ -70,10 +47,6 @@ cloud_provider:
Note that if you choose no cloud provider, media files won't work. Note that if you choose no cloud provider, media files won't work.
custom_bootstrap_compilation:
Indicates whether the project should support Bootstrap recompilation
via the selected JavaScript task runner's task. This can be useful
for real-time Bootstrap variable alteration.
use_compressor: use_compressor:
Indicates whether the project should be configured to use `Django Compressor`_. Indicates whether the project should be configured to use `Django Compressor`_.
@ -97,17 +70,6 @@ use_heroku:
use_travisci: use_travisci:
Indicates whether the project should be configured to use `Travis CI`_. Indicates whether the project should be configured to use `Travis CI`_.
keep_local_envs_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
is strongly encouraged).
Note: .env(s) are only utilized when Docker Compose and/or Heroku support is enabled.
debug:
Indicates whether the project should be configured for debugging.
This option is relevant for Cookiecutter Django developers only.
.. _MIT: https://opensource.org/licenses/MIT .. _MIT: https://opensource.org/licenses/MIT
.. _BSD: https://opensource.org/licenses/BSD-3-Clause .. _BSD: https://opensource.org/licenses/BSD-3-Clause
.. _GPLv3: https://www.gnu.org/licenses/gpl.html .. _GPLv3: https://www.gnu.org/licenses/gpl.html

View File

@ -91,7 +91,7 @@ def remove_packagejson_file():
def remove_celery_files(): def remove_celery_files():
file_names = [ file_names = [
os.path.join("config", "celery_app.py"), os.path.join("{{ cookiecutter.project_slug }}", "celery_app.py"),
os.path.join("{{ cookiecutter.project_slug }}", "users", "tasks.py"), os.path.join("{{ cookiecutter.project_slug }}", "users", "tasks.py"),
os.path.join( os.path.join(
"{{ cookiecutter.project_slug }}", "users", "tests", "test_tasks.py" "{{ cookiecutter.project_slug }}", "users", "tests", "test_tasks.py"
@ -261,8 +261,12 @@ def set_flags_in_envs(postgres_user, celery_flower_user, debug=False):
def set_flags_in_settings_files(): def set_flags_in_settings_files():
set_django_secret_key(os.path.join("config", "settings", "local.py")) set_django_secret_key(
set_django_secret_key(os.path.join("config", "settings", "test.py")) os.path.join("{{ cookiecutter.project_slug }}", "settings", "dev_template.py")
)
set_django_secret_key(
os.path.join("{{ cookiecutter.project_slug }}", "settings", "test.py")
)
def remove_envs_and_associated_files(): def remove_envs_and_associated_files():
@ -280,13 +284,8 @@ def remove_node_dockerfile():
def main(): def main():
debug = "{{ cookiecutter.debug }}".lower() == "y" set_flags_in_envs(generate_random_user(), generate_random_user())
set_flags_in_envs(
DEBUG_VALUE if debug else generate_random_user(),
DEBUG_VALUE if debug else generate_random_user(),
debug=debug,
)
set_flags_in_settings_files() set_flags_in_settings_files()
if "{{ cookiecutter.open_source_license }}" == "Not open source": if "{{ cookiecutter.open_source_license }}" == "Not open source":
@ -294,39 +293,11 @@ def main():
if "{{ cookiecutter.open_source_license}}" != "GPLv3": if "{{ cookiecutter.open_source_license}}" != "GPLv3":
remove_gplv3_files() remove_gplv3_files()
if "{{ cookiecutter.use_pycharm }}".lower() == "n": remove_utility_files()
remove_pycharm_files() remove_heroku_files()
if "{{ cookiecutter.use_docker }}".lower() == "y": append_to_gitignore_file(".env")
remove_utility_files() append_to_gitignore_file(".envs/*")
else:
remove_docker_files()
if "{{ cookiecutter.use_heroku }}".lower() == "n":
remove_heroku_files()
if (
"{{ cookiecutter.use_docker }}".lower() == "n"
and "{{ cookiecutter.use_heroku }}".lower() == "n"
):
if "{{ cookiecutter.keep_local_envs_in_vcs }}".lower() == "y":
print(
INFO + ".env(s) are only utilized when Docker Compose and/or "
"Heroku support is enabled so keeping them does not "
"make sense given your current setup." + TERMINATOR
)
remove_envs_and_associated_files()
else:
append_to_gitignore_file(".env")
append_to_gitignore_file(".envs/*")
if "{{ cookiecutter.keep_local_envs_in_vcs }}".lower() == "y":
append_to_gitignore_file("!.envs/.local/")
if "{{ cookiecutter.js_task_runner}}".lower() == "none":
remove_gulp_files()
remove_packagejson_file()
if "{{ cookiecutter.use_docker }}".lower() == "y":
remove_node_dockerfile()
if "{{ cookiecutter.cloud_provider}}".lower() == "none": if "{{ cookiecutter.cloud_provider}}".lower() == "none":
print( print(
@ -336,8 +307,7 @@ def main():
if "{{ cookiecutter.use_celery }}".lower() == "n": if "{{ cookiecutter.use_celery }}".lower() == "n":
remove_celery_files() remove_celery_files()
if "{{ cookiecutter.use_docker }}".lower() == "y": remove_celery_compose_dirs()
remove_celery_compose_dirs()
if "{{ cookiecutter.use_travisci }}".lower() == "n": if "{{ cookiecutter.use_travisci }}".lower() == "n":
remove_dottravisyml_file() remove_dottravisyml_file()

View File

@ -29,33 +29,3 @@ assert (
assert ( assert (
"\\" not in "{{ cookiecutter.author_name }}" "\\" not in "{{ cookiecutter.author_name }}"
), "Don't include backslashes in author name." ), "Don't include backslashes in author name."
if "{{ cookiecutter.use_docker }}".lower() == "n":
python_major_version = sys.version_info[0]
if python_major_version == 2:
print(
WARNING + "You're running cookiecutter under Python 2, but the generated "
"project requires Python 3.6+. Do you want to proceed (y/n)? " + TERMINATOR
)
yes_options, no_options = frozenset(["y"]), frozenset(["n"])
while True:
choice = raw_input().lower()
if choice in yes_options:
break
elif choice in no_options:
print(INFO + "Generation process stopped as requested." + TERMINATOR)
sys.exit(1)
else:
print(
HINT
+ "Please respond with {} or {}: ".format(
", ".join(
["'{}'".format(o) for o in yes_options if not o == ""]
),
", ".join(
["'{}'".format(o) for o in no_options if not o == ""]
),
)
+ TERMINATOR
)

View File

@ -30,8 +30,6 @@ def context():
@pytest_fixture_plus @pytest_fixture_plus
@pytest.mark.parametrize("windows", YN_CHOICES, ids=lambda yn: f"win:{yn}")
@pytest.mark.parametrize("use_docker", YN_CHOICES, ids=lambda yn: f"docker:{yn}")
@pytest.mark.parametrize("use_celery", YN_CHOICES, ids=lambda yn: f"celery:{yn}") @pytest.mark.parametrize("use_celery", YN_CHOICES, ids=lambda yn: f"celery:{yn}")
@pytest.mark.parametrize("use_mailhog", YN_CHOICES, ids=lambda yn: f"mailhog:{yn}") @pytest.mark.parametrize("use_mailhog", YN_CHOICES, ids=lambda yn: f"mailhog:{yn}")
@pytest.mark.parametrize("use_sentry", YN_CHOICES, ids=lambda yn: f"sentry:{yn}") @pytest.mark.parametrize("use_sentry", YN_CHOICES, ids=lambda yn: f"sentry:{yn}")
@ -39,19 +37,10 @@ def context():
@pytest.mark.parametrize("use_whitenoise", YN_CHOICES, ids=lambda yn: f"wnoise:{yn}") @pytest.mark.parametrize("use_whitenoise", YN_CHOICES, ids=lambda yn: f"wnoise:{yn}")
@pytest.mark.parametrize("cloud_provider", CLOUD_CHOICES, ids=lambda yn: f"cloud:{yn}") @pytest.mark.parametrize("cloud_provider", CLOUD_CHOICES, ids=lambda yn: f"cloud:{yn}")
def context_combination( def context_combination(
windows, use_celery, use_mailhog, use_sentry, use_compressor, use_whitenoise, cloud_provider
use_docker,
use_celery,
use_mailhog,
use_sentry,
use_compressor,
use_whitenoise,
cloud_provider,
): ):
"""Fixture that parametrize the function where it's used.""" """Fixture that parametrize the function where it's used."""
return { return {
"windows": windows,
"use_docker": use_docker,
"use_compressor": use_compressor, "use_compressor": use_compressor,
"use_celery": use_celery, "use_celery": use_celery,
"use_mailhog": use_mailhog, "use_mailhog": use_mailhog,
@ -125,7 +114,8 @@ def test_black_passes(cookies, context_combination):
This is parametrized for each combination from ``context_combination`` fixture This is parametrized for each combination from ``context_combination`` fixture
""" """
result = cookies.bake(extra_context=context_combination) result = cookies.bake(extra_context=context_combination)
if result.exception:
pytest.fail(str(result.exception))
try: try:
sh.black("--check", "--diff", "--exclude", "migrations", f"{result.project}/") sh.black("--check", "--diff", "--exclude", "migrations", f"{result.project}/")
except sh.ErrorReturnCode as e: except sh.ErrorReturnCode as e:

View File

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

View File

@ -161,7 +161,6 @@ typings/
!.vscode/extensions.json !.vscode/extensions.json
{% if cookiecutter.use_pycharm == 'y' -%}
# Provided default Pycharm Run/Debug Configurations should be tracked by git # Provided default Pycharm Run/Debug Configurations should be tracked by git
# In case of local modifications made by Pycharm, use update-index command # In case of local modifications made by Pycharm, use update-index command
# for each changed file, like this: # for each changed file, like this:
@ -216,7 +215,6 @@ com_crashlytics_export_strings.xml
crashlytics.properties crashlytics.properties
crashlytics-build.properties crashlytics-build.properties
fabric.properties fabric.properties
{% endif %}
### Windows template ### Windows template
@ -321,23 +319,19 @@ Session.vim
# Auto-generated tag files # Auto-generated tag files
tags tags
{% if cookiecutter.use_docker == 'n' %}
### VirtualEnv template ### VirtualEnv template
# Virtualenv # Virtualenv
pyvenv.cfg pyvenv.cfg
pip-selfcheck.json pip-selfcheck.json
.env .env
{% endif %}
### Project template ### Project template
{% if cookiecutter.use_mailhog == 'y' and cookiecutter.use_docker == 'n' %} {% if cookiecutter.use_mailhog == 'y' %}
MailHog MailHog
{%- endif %} {%- endif %}
{{ cookiecutter.project_slug }}/media/ {{ cookiecutter.project_slug }}/media/
.pytest_cache/ .pytest_cache/
{% if cookiecutter.use_docker == 'y' %}
.ipython/ .ipython/
{%- endif %}

View File

@ -13,13 +13,7 @@
</facet> </facet>
</component> </component>
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
{% if cookiecutter.js_task_runner != 'None' %} <content url="file://$MODULE_DIR$" />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/node_modules" />
</content>
{% else %}
<content url="file://$MODULE_DIR$" />
{% endif %}
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
<component name="PackageRequirementsSettings"> <component name="PackageRequirementsSettings">

View File

@ -88,37 +88,12 @@ Please note: For Celery's import magic to work, it is important *where* the cele
Email Server Email Server
^^^^^^^^^^^^ ^^^^^^^^^^^^
{% if cookiecutter.use_docker == 'y' %}
In development, it is often nice to be able to see emails that are being sent from your application. For that reason local SMTP server `MailHog`_ with a web interface is available as docker container. In development, it is often nice to be able to see emails that are being sent from your application. For that reason local SMTP server `MailHog`_ with a web interface is available as docker container.
Container mailhog will start automatically when you will run all docker containers. Container mailhog will start automatically when you will run all docker containers.
Please check `cookiecutter-django Docker documentation`_ for more details how to start all containers. Please check `cookiecutter-django Docker documentation`_ for more details how to start all containers.
With MailHog running, to view messages that are sent by your application, open your browser and go to ``http://127.0.0.1:8025`` With MailHog running, to view messages that are sent by your application, open your browser and go to ``http://127.0.0.1:8025``
{% else %}
In development, it is often nice to be able to see emails that are being sent from your application. If you choose to use `MailHog`_ when generating the project a local SMTP server with a web interface will be available.
#. `Download the latest MailHog release`_ for your OS.
#. Rename the build to ``MailHog``.
#. Copy the file to the project root.
#. Make it executable: ::
$ chmod +x MailHog
#. Spin up another terminal window and start it there: ::
./MailHog
#. Check out `<http://127.0.0.1:8025/>`_ to see how it goes.
Now you have your own mail server running locally, ready to receive whatever you send it.
.. _`Download the latest MailHog release`: https://github.com/mailhog/MailHog/releases
{% endif %}
.. _mailhog: https://github.com/mailhog/MailHog
{% endif %} {% endif %}
{% if cookiecutter.use_sentry == "y" %} {% if cookiecutter.use_sentry == "y" %}
@ -135,16 +110,6 @@ Deployment
---------- ----------
The following details how to deploy this application. The following details how to deploy this application.
{% if cookiecutter.use_heroku.lower() == "y" %}
Heroku
^^^^^^
See detailed `cookiecutter-django Heroku documentation`_.
.. _`cookiecutter-django Heroku documentation`: http://cookiecutter-django.readthedocs.io/en/latest/deployment-on-heroku.html
{% endif %}
{% if cookiecutter.use_docker.lower() == "y" %}
Docker Docker
^^^^^^ ^^^^^^
@ -152,22 +117,4 @@ Docker
See detailed `cookiecutter-django Docker documentation`_. See detailed `cookiecutter-django Docker documentation`_.
.. _`cookiecutter-django Docker documentation`: http://cookiecutter-django.readthedocs.io/en/latest/deployment-with-docker.html .. _`cookiecutter-django Docker documentation`: http://cookiecutter-django.readthedocs.io/en/latest/deployment-with-docker.html
{% endif %}
{% if cookiecutter.custom_bootstrap_compilation == "y" %}
Custom Bootstrap Compilation
^^^^^^
The generated CSS is set up with automatic Bootstrap recompilation with variables of your choice.
Bootstrap v4 is installed using npm and customised by tweaking your variables in ``static/sass/custom_bootstrap_vars``.
You can find a list of available variables `in the bootstrap source`_, or get explanations on them in the `Bootstrap docs`_.
{% if cookiecutter.js_task_runner == 'Gulp' %}
Bootstrap's javascript as well as its dependencies is concatenated into a single file: ``static/js/vendors.js``.
{% endif %}
.. _in the bootstrap source: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_variables.scss
.. _Bootstrap docs: https://getbootstrap.com/docs/4.1/getting-started/theming/
{% endif %}

View File

@ -1,4 +1,3 @@
{% if cookiecutter.js_task_runner == 'Gulp' -%}
FROM node:10-stretch-slim as client-builder FROM node:10-stretch-slim as client-builder
WORKDIR /app WORKDIR /app
@ -8,7 +7,6 @@ COPY . /app
RUN npm run build RUN npm run build
# Python build stage # Python build stage
{%- endif %}
FROM python:3.6-alpine FROM python:3.6-alpine
ENV PYTHONUNBUFFERED 1 ENV PYTHONUNBUFFERED 1
@ -56,11 +54,7 @@ RUN sed -i 's/\r$//g' /start-flower
RUN chmod +x /start-flower RUN chmod +x /start-flower
{%- endif %} {%- endif %}
{%- if cookiecutter.js_task_runner == 'Gulp' %}
COPY --from=client-builder /app /app COPY --from=client-builder /app /app
{% else %}
COPY . /app
{%- endif %}
RUN chown -R django /app RUN chown -R django /app

View File

@ -1,4 +1,4 @@
FROM postgres:{{ cookiecutter.postgresql_version }} FROM postgres:11-alpine
COPY ./compose/production/postgres/maintenance /usr/local/bin/maintenance COPY ./compose/production/postgres/maintenance /usr/local/bin/maintenance
RUN chmod +x /usr/local/bin/maintenance/* RUN chmod +x /usr/local/bin/maintenance/*

View File

@ -1,7 +0,0 @@
{% if cookiecutter.use_celery == 'y' -%}
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery_app import app as celery_app
__all__ = ("celery_app",)
{% endif -%}

View File

@ -1,305 +0,0 @@
{% if cookiecutter.use_sentry == 'y' -%}
import logging
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.logging import LoggingIntegration
{%- if cookiecutter.use_celery == 'y' %}
from sentry_sdk.integrations.celery import CeleryIntegration
{% endif %}
{% endif -%}
from .base import * # noqa
from .base import env
# GENERAL
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
SECRET_KEY = env("DJANGO_SECRET_KEY")
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["{{ cookiecutter.domain_name }}"])
# DATABASES
# ------------------------------------------------------------------------------
DATABASES["default"] = env.db("DATABASE_URL") # noqa F405
DATABASES["default"]["ATOMIC_REQUESTS"] = True # noqa F405
DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60) # noqa F405
# CACHES
# ------------------------------------------------------------------------------
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": env("REDIS_URL"),
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
# Mimicing memcache behavior.
# http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior
"IGNORE_EXCEPTIONS": True,
},
}
}
# SECURITY
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-ssl-redirect
SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True)
# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-secure
SESSION_COOKIE_SECURE = True
# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-secure
CSRF_COOKIE_SECURE = True
# https://docs.djangoproject.com/en/dev/topics/security/#ssl-https
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-seconds
# TODO: set this to 60 seconds first and then to 518400 once you prove the former works
SECURE_HSTS_SECONDS = 60
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-include-subdomains
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool(
"DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True
)
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-preload
SECURE_HSTS_PRELOAD = env.bool("DJANGO_SECURE_HSTS_PRELOAD", default=True)
# https://docs.djangoproject.com/en/dev/ref/middleware/#x-content-type-options-nosniff
SECURE_CONTENT_TYPE_NOSNIFF = env.bool(
"DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True
)
{% if cookiecutter.cloud_provider != 'None' -%}
# STORAGES
# ------------------------------------------------------------------------------
# https://django-storages.readthedocs.io/en/latest/#installation
INSTALLED_APPS += ["storages"] # noqa F405
{%- endif -%}
{% if cookiecutter.cloud_provider == 'AWS' %}
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID")
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_SECRET_ACCESS_KEY = env("DJANGO_AWS_SECRET_ACCESS_KEY")
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME")
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_QUERYSTRING_AUTH = False
# DO NOT change these unless you know what you're doing.
_AWS_EXPIRY = 60 * 60 * 24 * 7
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
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)
{% elif cookiecutter.cloud_provider == 'GCP' %}
DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
GS_BUCKET_NAME = env("DJANGO_GCP_STORAGE_BUCKET_NAME")
GS_DEFAULT_ACL = "publicRead"
{% endif -%}
{% if cookiecutter.cloud_provider != 'None' or cookiecutter.use_whitenoise == 'y' -%}
# STATIC
# ------------------------
{% endif -%}
{% if cookiecutter.use_whitenoise == 'y' -%}
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
{% elif cookiecutter.cloud_provider == 'AWS' -%}
STATICFILES_STORAGE = "config.settings.production.StaticRootS3Boto3Storage"
STATIC_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/static/"
{% elif cookiecutter.cloud_provider == 'GCP' -%}
STATIC_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/static/"
{% endif -%}
# MEDIA
# ------------------------------------------------------------------------------
{%- if cookiecutter.cloud_provider == 'AWS' %}
# region http://stackoverflow.com/questions/10390244/
# 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/"
{%- elif cookiecutter.cloud_provider == 'GCP' %}
MEDIA_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/"
MEDIA_ROOT = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/"
{%- endif %}
# TEMPLATES
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#templates
TEMPLATES[0]["OPTIONS"]["loaders"] = [ # noqa F405
(
"django.template.loaders.cached.Loader",
[
"django.template.loaders.filesystem.Loader",
"django.template.loaders.app_directories.Loader",
],
)
]
# EMAIL
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email
DEFAULT_FROM_EMAIL = env(
"DJANGO_DEFAULT_FROM_EMAIL", default="{{cookiecutter.project_name}} <noreply@{{cookiecutter.domain_name}}>"
)
# https://docs.djangoproject.com/en/dev/ref/settings/#server-email
SERVER_EMAIL = env("DJANGO_SERVER_EMAIL", default=DEFAULT_FROM_EMAIL)
# https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix
EMAIL_SUBJECT_PREFIX = env(
"DJANGO_EMAIL_SUBJECT_PREFIX", default="[{{cookiecutter.project_name}}]"
)
# ADMIN
# ------------------------------------------------------------------------------
# Django Admin URL regex.
ADMIN_URL = env("DJANGO_ADMIN_URL")
# Anymail (Mailgun)
# ------------------------------------------------------------------------------
# https://anymail.readthedocs.io/en/stable/installation/#installing-anymail
INSTALLED_APPS += ["anymail"] # noqa F405
EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend"
# https://anymail.readthedocs.io/en/stable/installation/#anymail-settings-reference
ANYMAIL = {
"MAILGUN_API_KEY": env("MAILGUN_API_KEY"),
"MAILGUN_SENDER_DOMAIN": env("MAILGUN_DOMAIN"),
"MAILGUN_API_URL": env("MAILGUN_API_URL", default="https://api.mailgun.net/v3"),
}
{% if cookiecutter.use_whitenoise == 'y' -%}
# WhiteNoise
# ------------------------------------------------------------------------------
# http://whitenoise.evans.io/en/latest/django.html#enable-whitenoise
MIDDLEWARE.insert(1, "whitenoise.middleware.WhiteNoiseMiddleware") # noqa F405
{% endif %}
{%- if cookiecutter.use_compressor == 'y' -%}
# django-compressor
# ------------------------------------------------------------------------------
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_ENABLED
COMPRESS_ENABLED = env.bool("COMPRESS_ENABLED", default=True)
# https://django-compressor.readthedocs.io/en/latest/settings/#django.conf.settings.COMPRESS_STORAGE
COMPRESS_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
# 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 %}
{% endif %}
{%- if cookiecutter.use_whitenoise == 'n' -%}
# Collectfast
# ------------------------------------------------------------------------------
# https://github.com/antonagestam/collectfast#installation
INSTALLED_APPS = ["collectfast"] + INSTALLED_APPS # noqa F405
AWS_PRELOAD_METADATA = True
{% endif %}
# LOGGING
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#logging
# See https://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
{% if cookiecutter.use_sentry == 'n' -%}
# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"filters": {"require_debug_false": {"()": "django.utils.log.RequireDebugFalse"}},
"formatters": {
"verbose": {
"format": "%(levelname)s %(asctime)s %(module)s "
"%(process)d %(thread)d %(message)s"
}
},
"handlers": {
"mail_admins": {
"level": "ERROR",
"filters": ["require_debug_false"],
"class": "django.utils.log.AdminEmailHandler",
},
"console": {
"level": "DEBUG",
"class": "logging.StreamHandler",
"formatter": "verbose",
},
},
"root": {"level": "INFO", "handlers": ["console"]},
"loggers": {
"django.request": {
"handlers": ["mail_admins"],
"level": "ERROR",
"propagate": True,
},
"django.security.DisallowedHost": {
"level": "ERROR",
"handlers": ["console", "mail_admins"],
"propagate": True,
},
},
}
{% else %}
LOGGING = {
"version": 1,
"disable_existing_loggers": True,
"formatters": {
"verbose": {
"format": "%(levelname)s %(asctime)s %(module)s "
"%(process)d %(thread)d %(message)s"
}
},
"handlers": {
"console": {
"level": "DEBUG",
"class": "logging.StreamHandler",
"formatter": "verbose",
}
},
"root": {"level": "INFO", "handlers": ["console"]},
"loggers": {
"django.db.backends": {
"level": "ERROR",
"handlers": ["console"],
"propagate": False,
},
# Errors logged by the SDK itself
"sentry_sdk": {"level": "ERROR", "handlers": ["console"], "propagate": False},
"django.security.DisallowedHost": {
"level": "ERROR",
"handlers": ["console"],
"propagate": False,
},
},
}
# Sentry
# ------------------------------------------------------------------------------
SENTRY_DSN = env("SENTRY_DSN")
SENTRY_LOG_LEVEL = env.int("DJANGO_SENTRY_LOG_LEVEL", logging.INFO)
sentry_logging = LoggingIntegration(
level=SENTRY_LOG_LEVEL, # Capture info and above as breadcrumbs
event_level=logging.ERROR, # Send errors as events
)
{%- if cookiecutter.use_celery == 'y' %}
sentry_sdk.init(
dsn=SENTRY_DSN,
integrations=[sentry_logging, DjangoIntegration(), CeleryIntegration()],
)
{% else %}
sentry_sdk.init(dsn=SENTRY_DSN, integrations=[sentry_logging, DjangoIntegration()])
{% endif -%}
{% endif %}
# Your stuff...
# ------------------------------------------------------------------------------

View File

@ -9,9 +9,6 @@ const pjson = require('./package.json')
// Plugins // Plugins
const autoprefixer = require('autoprefixer') const autoprefixer = require('autoprefixer')
const browserSync = require('browser-sync').create() const browserSync = require('browser-sync').create()
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
const concat = require('gulp-concat')
{% endif %}
const cssnano = require ('cssnano') const cssnano = require ('cssnano')
const imagemin = require('gulp-imagemin') const imagemin = require('gulp-imagemin')
const pixrem = require('pixrem') const pixrem = require('pixrem')
@ -29,14 +26,6 @@ function pathsConfig(appName) {
const vendorsRoot = 'node_modules' const vendorsRoot = 'node_modules'
return { return {
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
bootstrapSass: `${vendorsRoot}/bootstrap/scss`,
vendorsJs: [
`${vendorsRoot}/jquery/dist/jquery.slim.js`,
`${vendorsRoot}/popper.js/dist/umd/popper.js`,
`${vendorsRoot}/bootstrap/dist/js/bootstrap.js`,
],
{% endif %}
app: this.app, app: this.app,
templates: `${this.app}/templates`, templates: `${this.app}/templates`,
css: `${this.app}/static/css`, css: `${this.app}/static/css`,
@ -67,9 +56,6 @@ function styles() {
return src(`${paths.sass}/project.scss`) return src(`${paths.sass}/project.scss`)
.pipe(sass({ .pipe(sass({
includePaths: [ includePaths: [
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
paths.bootstrapSass,
{% endif %}
paths.sass paths.sass
] ]
}).on('error', sass.logError)) }).on('error', sass.logError))
@ -90,19 +76,6 @@ function scripts() {
.pipe(dest(paths.js)) .pipe(dest(paths.js))
} }
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
// Vendor Javascript minification
function vendorScripts() {
return src(paths.vendorsJs)
.pipe(concat('vendors.js'))
.pipe(dest(paths.js))
.pipe(plumber()) // Checks for errors
.pipe(uglify()) // Minifies the js
.pipe(rename({ suffix: '.min' }))
.pipe(dest(paths.js))
}
{% endif %}
// Image compression // Image compression
function imgCompression() { function imgCompression() {
return src(`${paths.images}/*`) return src(`${paths.images}/*`)
@ -128,22 +101,7 @@ function initBrowserSync() {
`${paths.templates}/*.html` `${paths.templates}/*.html`
], { ], {
// https://www.browsersync.io/docs/options/#option-proxy // https://www.browsersync.io/docs/options/#option-proxy
{%- if cookiecutter.use_docker == 'n' %}
proxy: 'localhost:8000' proxy: 'localhost:8000'
{% else %}
proxy: {
target: 'django:8000',
proxyReq: [
function(proxyReq, req) {
// Assign proxy "host" header same as current request at Browsersync server
proxyReq.setHeader('Host', req.headers.host)
}
]
},
// https://www.browsersync.io/docs/options/#option-open
// Disable as it doesn't work from inside a container
open: false
{%- endif %}
} }
) )
} }
@ -159,15 +117,12 @@ function watchPaths() {
const generateAssets = parallel( const generateAssets = parallel(
styles, styles,
scripts, scripts,
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}vendorScripts,{% endif %}
imgCompression imgCompression
) )
// Set up dev environment // Set up dev environment
const dev = parallel( const dev = parallel(
{%- if cookiecutter.use_docker == 'n' %}
runServer, runServer,
{%- endif %}
initBrowserSync, initBrowserSync,
watchPaths watchPaths
) )

View File

@ -79,7 +79,6 @@ services:
command: /start-flower command: /start-flower
{%- endif %} {%- endif %}
{%- if cookiecutter.js_task_runner == 'Gulp' %}
node: node:
build: build:
@ -97,5 +96,3 @@ services:
- "3000:3000" - "3000:3000"
# Expose browsersync UI: https://www.browsersync.io/docs/options/#option-ui # Expose browsersync UI: https://www.browsersync.io/docs/options/#option-ui
- "3001:3001" - "3001:3001"
{%- endif %}

View File

@ -3,13 +3,6 @@
"version": "{{ cookiecutter.version }}", "version": "{{ cookiecutter.version }}",
"dependencies": {}, "dependencies": {},
"devDependencies": { "devDependencies": {
{% if cookiecutter.js_task_runner == 'Gulp' -%}
{% if cookiecutter.custom_bootstrap_compilation == 'y' -%}
"bootstrap": "4.3.1",
"gulp-concat": "^2.6.1",
"jquery": "3.3.1",
"popper.js": "1.14.3",
{% endif -%}
"autoprefixer": "^9.4.7", "autoprefixer": "^9.4.7",
"browser-sync": "^2.14.0", "browser-sync": "^2.14.0",
"cssnano": "^4.1.10", "cssnano": "^4.1.10",
@ -21,7 +14,6 @@
"gulp-sass": "^4.0.2", "gulp-sass": "^4.0.2",
"gulp-uglify-es": "^1.0.4", "gulp-uglify-es": "^1.0.4",
"pixrem": "^5.0.0" "pixrem": "^5.0.0"
{%- endif %}
}, },
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@ -30,9 +22,7 @@
"last 2 versions" "last 2 versions"
], ],
"scripts": { "scripts": {
{% if cookiecutter.js_task_runner == 'Gulp' -%}
"dev": "gulp", "dev": "gulp",
"build": "gulp generate-assets" "build": "gulp generate-assets"
{%- endif %}
} }
} }

View File

@ -1,5 +1,3 @@
[pytest] [pytest]
addopts = --ds=config.settings.test addopts = --ds=config.settings.test
{%- if cookiecutter.js_task_runner != 'None' %}
norecursedirs = node_modules norecursedirs = node_modules
{%- endif %}

View File

@ -2,7 +2,7 @@ pytz==2019.1 # https://github.com/stub42/pytz
python-slugify==3.0.2 # https://github.com/un33k/python-slugify python-slugify==3.0.2 # https://github.com/un33k/python-slugify
Pillow==6.1.0 # https://github.com/python-pillow/Pillow Pillow==6.1.0 # 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 # https://github.com/ndparker/rcssmin
{%- endif %} {%- endif %}
argon2-cffi==19.1.0 # https://github.com/hynek/argon2_cffi argon2-cffi==19.1.0 # https://github.com/hynek/argon2_cffi
{%- if cookiecutter.use_whitenoise == 'y' %} {%- if cookiecutter.use_whitenoise == 'y' %}
@ -12,10 +12,8 @@ redis==3.2.1 # https://github.com/antirez/redis
{%- if cookiecutter.use_celery == "y" %} {%- if cookiecutter.use_celery == "y" %}
celery==4.3.0 # pyup: < 5.0 # https://github.com/celery/celery celery==4.3.0 # pyup: < 5.0 # https://github.com/celery/celery
django-celery-beat==1.5.0 # https://github.com/celery/django-celery-beat django-celery-beat==1.5.0 # https://github.com/celery/django-celery-beat
{%- if cookiecutter.use_docker == 'y' %}
flower==0.9.3 # https://github.com/mher/flower flower==0.9.3 # https://github.com/mher/flower
{%- endif %} {%- endif %}
{%- endif %}
# Django # Django
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -3,11 +3,7 @@
Werkzeug==0.14.1 # pyup: < 0.15 # 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.1.2 # https://github.com/sphinx-doc/sphinx Sphinx==2.1.2 # https://github.com/sphinx-doc/sphinx
{%- if cookiecutter.use_docker == 'y' %}
psycopg2==2.8.3 --no-binary psycopg2 # https://github.com/psycopg/psycopg2
{%- else %}
psycopg2-binary==2.8.3 # https://github.com/psycopg/psycopg2 psycopg2-binary==2.8.3 # https://github.com/psycopg/psycopg2
{%- endif %}
# Testing # Testing
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -35,7 +35,5 @@ if [ -z "$VIRTUAL_ENV" ]; then
else else
pip install -r $PROJECT_DIR/requirements/local.txt pip install -r $PROJECT_DIR/requirements/local.txt
{% if cookiecutter.use_heroku == "y" -%}
pip install -r $PROJECT_DIR/requirements.txt pip install -r $PROJECT_DIR/requirements.txt
{%- endif %}
fi fi

View File

@ -0,0 +1,4 @@
try:
from .dev import * # NOQA
except ImportError:
from .prod import * # NOQA

View File

@ -1,7 +1,21 @@
""" """
Base settings to build other settings files upon. Base settings to build other settings files upon.
""" """
{% if cookiecutter.use_sentry == 'y' -%}
import logging
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.logging import LoggingIntegration
{%- if cookiecutter.use_celery == 'y' %}
from sentry_sdk.integrations.celery import CeleryIntegration
{% endif %}{% endif -%}
{% if cookiecutter.cloud_provider == 'AWS' %}
from storages.backends.s3boto3 import S3Boto3Storage
{% elif cookiecutter.cloud_provider == 'Azure' %}
from storages.backends.azure_storage import AzureStorage
{%- endif %}
import environ import environ
ROOT_DIR = ( ROOT_DIR = (
@ -11,51 +25,29 @@ APPS_DIR = ROOT_DIR.path("{{ cookiecutter.project_slug }}")
env = environ.Env() env = environ.Env()
READ_DOT_ENV_FILE = env.bool("DJANGO_READ_DOT_ENV_FILE", default=False) # OS environment variables take precedence over variables from .env
if READ_DOT_ENV_FILE: env.read_env(str(ROOT_DIR.path(".env")))
# OS environment variables take precedence over variables from .env
env.read_env(str(ROOT_DIR.path(".env")))
# GENERAL # GENERAL
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
DEBUG = env.bool("DJANGO_DEBUG", False) DEBUG = env.bool("DJANGO_DEBUG", False)
# Local time zone. Choices are
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# though not all of them may be available with every OS.
# In Windows, this must be set to your system time zone.
TIME_ZONE = "{{ cookiecutter.timezone }}"
# https://docs.djangoproject.com/en/dev/ref/settings/#language-code
LANGUAGE_CODE = "en-us"
# https://docs.djangoproject.com/en/dev/ref/settings/#site-id
SITE_ID = 1 SITE_ID = 1
# https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["{{ cookiecutter.domain_name }}"])
USE_I18N = True
# https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n
USE_L10N = True
# https://docs.djangoproject.com/en/dev/ref/settings/#use-tz
USE_TZ = True
# https://docs.djangoproject.com/en/dev/ref/settings/#locale-paths
LOCALE_PATHS = [ROOT_DIR.path("locale")]
# DATABASES # DATABASES
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#databases # https://docs.djangoproject.com/en/dev/ref/settings/#databases
{% if cookiecutter.use_docker == "y" -%} # ------------------------------------------------------------------------------
DATABASES = {"default": env.db("DATABASE_URL")} DATABASES = {"default": env.db("DATABASE_URL")}
{%- else %}
DATABASES = {
"default": env.db("DATABASE_URL", default="postgres://{% if cookiecutter.windows == 'y' %}localhost{% endif %}/{{cookiecutter.project_slug}}")
}
{%- endif %}
DATABASES["default"]["ATOMIC_REQUESTS"] = True DATABASES["default"]["ATOMIC_REQUESTS"] = True
DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60)
# URLS # URLS
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf ROOT_URLCONF = "{{ cookiecutter.project_slug }}.urls"
ROOT_URLCONF = "config.urls" WSGI_APPLICATION = "{{ cookiecutter.project_slug }}.wsgi.application"
# https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
WSGI_APPLICATION = "config.wsgi.application"
# APPS # APPS
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -70,7 +62,6 @@ DJANGO_APPS = [
"django.contrib.admin", "django.contrib.admin",
] ]
THIRD_PARTY_APPS = [ THIRD_PARTY_APPS = [
"crispy_forms",
"allauth", "allauth",
"allauth.account", "allauth.account",
"allauth.socialaccount", "allauth.socialaccount",
@ -78,37 +69,84 @@ THIRD_PARTY_APPS = [
{%- if cookiecutter.use_celery == 'y' %} {%- if cookiecutter.use_celery == 'y' %}
"django_celery_beat", "django_celery_beat",
{%- endif %} {%- endif %}
{%- if cookiecutter.use_compressor == 'y' %}
"compressor",
{%- endif %}
{%- if cookiecutter.cloud_provider != 'None' %}
"storages",
{%- endif %}
] ]
LOCAL_APPS = [ LOCAL_APPS = [
"{{ cookiecutter.project_slug }}.users.apps.UsersConfig", "{{ cookiecutter.project_slug }}.users.apps.UsersConfig",
# Your stuff: custom apps go here # Your stuff: custom apps go here
] ]
# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
# MIGRATIONS
# CACHES
# https://docs.djangoproject.com/en/2.2/ref/settings/#caches
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": env("REDIS_URL"),
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
# Mimicing memcache behavior.
# http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior
"IGNORE_EXCEPTIONS": True,
},
}
}
# SECURITY
# ------------------------------------------------------------------------------
CSRF_COOKIE_HTTPONLY = True
CSRF_COOKIE_SECURE = True
SECRET_KEY = env("DJANGO_SECRET_KEY")
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True)
# TODO: set this to 60 seconds first and then to 518400 once you prove the former works
SECURE_HSTS_SECONDS = 60
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool(
"DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True
)
SECURE_HSTS_PRELOAD = env.bool("DJANGO_SECURE_HSTS_PRELOAD", default=True)
SECURE_CONTENT_TYPE_NOSNIFF = env.bool(
"DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True
)
SECURE_BROWSER_XSS_FILTER = True
X_FRAME_OPTIONS = "DENY"
# SESSIONS
# https://docs.djangoproject.com/en/2.2/ref/settings/#sessions
# ------------------------------------------------------------------------------
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SECURE = True
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
# MIGRATIONS
# https://docs.djangoproject.com/en/dev/ref/settings/#migration-modules # https://docs.djangoproject.com/en/dev/ref/settings/#migration-modules
# ------------------------------------------------------------------------------
MIGRATION_MODULES = {"sites": "{{ cookiecutter.project_slug }}.contrib.sites.migrations"} MIGRATION_MODULES = {"sites": "{{ cookiecutter.project_slug }}.contrib.sites.migrations"}
# AUTHENTICATION # AUTHENTICATION
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#authentication-backends
AUTHENTICATION_BACKENDS = [ AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend", "django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend", "allauth.account.auth_backends.AuthenticationBackend",
] ]
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model
AUTH_USER_MODEL = "users.User" AUTH_USER_MODEL = "users.User"
# https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url
LOGIN_REDIRECT_URL = "users:redirect"
# https://docs.djangoproject.com/en/dev/ref/settings/#login-url
LOGIN_URL = "account_login"
# PASSWORDS # use named URL patterns instead of hardcoded paths
# ------------------------------------------------------------------------------ LOGIN_REDIRECT_URL = "users:redirect"
# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers LOGIN_URL = "account_login"
PASSWORD_HASHERS = [ PASSWORD_HASHERS = [
# https://docs.djangoproject.com/en/dev/topics/auth/passwords/#using-argon2-with-django # https://docs.djangoproject.com/en/dev/topics/auth/passwords/#using-argon2-with-django
"django.contrib.auth.hashers.Argon2PasswordHasher", "django.contrib.auth.hashers.Argon2PasswordHasher",
@ -116,7 +154,6 @@ PASSWORD_HASHERS = [
"django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher", "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
"django.contrib.auth.hashers.BCryptSHA256PasswordHasher", "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
] ]
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [ AUTH_PASSWORD_VALIDATORS = [
{ {
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator" "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
@ -127,10 +164,13 @@ AUTH_PASSWORD_VALIDATORS = [
] ]
# MIDDLEWARE # MIDDLEWARE
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#middleware # https://docs.djangoproject.com/en/dev/ref/settings/#middleware
# ------------------------------------------------------------------------------
MIDDLEWARE = [ MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware", "django.middleware.security.SecurityMiddleware",
{%- if cookiecutter.use_whitenoise == 'y' %}
"whitenoise.middleware.WhiteNoiseMiddleware",
{%- endif %}
"django.contrib.sessions.middleware.SessionMiddleware", "django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware", "django.middleware.locale.LocaleMiddleware",
"django.middleware.common.CommonMiddleware", "django.middleware.common.CommonMiddleware",
@ -140,44 +180,131 @@ MIDDLEWARE = [
"django.middleware.clickjacking.XFrameOptionsMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware",
] ]
# STATIC
# Globalization (i18n/l10n)
# https://docs.djangoproject.com/en/2.2/ref/settings/#globalization-i18n-l10n
# ------------------------------------------------------------------------------
TIME_ZONE = "{{ cookiecutter.timezone }}"
LANGUAGE_CODE = "en-us"
USE_I18N = True
USE_L10N = True
USE_TZ = True
LOCALE_PATHS = [ROOT_DIR.path("locale")]
{%- if cookiecutter.cloud_provider != 'None' %}
# STORAGES
# https://django-storages.readthedocs.io/en/latest/#installation
# ------------------------------------------------------------------------------
{% if cookiecutter.cloud_provider == 'AWS' %}
# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings
AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = env("DJANGO_AWS_SECRET_ACCESS_KEY")
AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME")
AWS_QUERYSTRING_AUTH = False
_AWS_EXPIRY = 60 * 60 * 24 * 7
AWS_S3_OBJECT_PARAMETERS = {
"CacheControl": f"max-age={_AWS_EXPIRY}, s-maxage={_AWS_EXPIRY}, must-revalidate"
}
AWS_DEFAULT_ACL = None
AWS_S3_REGION_NAME = env("DJANGO_AWS_S3_REGION_NAME", default=None)
{% elif cookiecutter.cloud_provider == 'GCP' %}
GS_BUCKET_NAME = env("DJANGO_GCP_STORAGE_BUCKET_NAME")
GS_DEFAULT_ACL = "publicRead"
{% elif cookiecutter.cloud_provider == 'Azure' %}
# https://django-storages.readthedocs.io/en/latest/backends/azure.html#install
AZURE_ACCOUNT_NAME = env("DJANGO_AZURE_ACCOUNT_NAME")
AZURE_ACCOUNT_KEY = env("DJANGO_AZURE_ACCOUNT_KEY")
AZURE_CONTAINER = env("DJANGO_AZURE_CONTAINER")
AZURE_URL_EXPIRATION_SECS = 60 * 60 * 24 * 7
{% endif -%}
# STATIC
# https://docs.djangoproject.com/en/2.2/ref/settings/#static-files
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#static-root
STATIC_ROOT = str(ROOT_DIR("staticfiles")) STATIC_ROOT = str(ROOT_DIR("staticfiles"))
# https://docs.djangoproject.com/en/dev/ref/settings/#static-url
STATIC_URL = "/static/"
# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
STATICFILES_DIRS = [str(APPS_DIR.path("static"))] STATICFILES_DIRS = [str(APPS_DIR.path("static"))]
# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
STATICFILES_FINDERS = [ STATICFILES_FINDERS = [
"django.contrib.staticfiles.finders.FileSystemFinder", "django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder", "django.contrib.staticfiles.finders.AppDirectoriesFinder",
{%- if cookiecutter.use_compressor == 'y' %}
"compressor.finders.CompressorFinder",
{%- endif %}
] ]
{%- if cookiecutter.cloud_provider == 'AWS' %}
# MEDIA
class StaticRootS3Boto3Storage(S3Boto3Storage):
location = "static"
default_acl = "public-read"
STATICFILES_STORAGE = "settings.base.StaticRootS3Boto3Storage"
STATIC_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/static/"
{% elif cookiecutter.cloud_provider == 'GCP' %}
STATICFILES_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
STATIC_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/static/"
{% elif cookiecutter.cloud_provider == 'Azure' %}
class PublicAzureStorage(AzureStorage):
account_name = AZURE_ACCOUNT_NAME
account_key = AZURE_ACCOUNT_KEY
azure_container = AZURE_CONTAINER
expiration_secs = None
STATICFILES_STORAGE = "settings.base.PublicAzureStorage"
{% elif cookiecutter.use_whitenoise == 'y' %}
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
{% else %}
STATIC_URL = "/static/"
{%- endif %}
{%- if cookiecutter.use_compressor == 'y' %}
COMPRESS_ENABLED = env.bool("COMPRESS_ENABLED", default=True)
COMPRESS_STORAGE = STATICFILES_STORAGE
COMPRESS_URL = STATIC_URL
{% endif %}
{%- endif %}
# FILE UPLOADS
# https://docs.djangoproject.com/en/2.2/ref/settings/#file-uploads
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#media-root {%- if cookiecutter.cloud_provider == 'AWS' %}
MEDIA_ROOT = str(APPS_DIR("media"))
# https://docs.djangoproject.com/en/dev/ref/settings/#media-url
class MediaRootS3Boto3Storage(S3Boto3Storage):
location = "media"
file_overwrite = False
DEFAULT_FILE_STORAGE = "config.settings.production.MediaRootS3Boto3Storage"
MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/"
{% elif cookiecutter.cloud_provider == 'GCP' %}
DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
MEDIA_URL = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/"
MEDIA_ROOT = f"https://storage.googleapis.com/{GS_BUCKET_NAME}/media/"
{% elif cookiecutter.cloud_provider == 'Azure' %}
DEFAULT_FILE_STORAGE = "storages.backends.azure_storage.AzureStorage"
{% else %}
MEDIA_ROOT = str(ROOT_DIR("media"))
MEDIA_URL = "/media/" MEDIA_URL = "/media/"
{%- endif %}
# TEMPLATES # TEMPLATES
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#templates # https://docs.djangoproject.com/en/dev/ref/settings/#templates
# ------------------------------------------------------------------------------
TEMPLATES = [ TEMPLATES = [
{ {
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND
"BACKEND": "django.template.backends.django.DjangoTemplates", "BACKEND": "django.template.backends.django.DjangoTemplates",
# https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
"DIRS": [str(APPS_DIR.path("templates"))], "DIRS": [str(APPS_DIR.path("templates"))],
"OPTIONS": { "OPTIONS": {
# https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
# https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
"loaders": [ "loaders": [
"django.template.loaders.filesystem.Loader", "django.template.loaders.filesystem.Loader",
"django.template.loaders.app_directories.Loader", "django.template.loaders.app_directories.Loader",
], ],
# https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
"context_processors": [ "context_processors": [
"django.template.context_processors.debug", "django.template.context_processors.debug",
"django.template.context_processors.request", "django.template.context_processors.request",
@ -191,46 +318,42 @@ TEMPLATES = [
}, },
} }
] ]
# http://django-crispy-forms.readthedocs.io/en/latest/install.html#template-packs
CRISPY_TEMPLATE_PACK = "bootstrap4"
# FIXTURES # FIXTURES
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#fixture-dirs # https://docs.djangoproject.com/en/dev/ref/settings/#fixture-dirs
FIXTURE_DIRS = (str(APPS_DIR.path("fixtures")),) FIXTURE_DIRS = (str(APPS_DIR.path("fixtures")),)
# SECURITY
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-httponly
SESSION_COOKIE_HTTPONLY = True
# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-httponly
CSRF_COOKIE_HTTPONLY = True
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-browser-xss-filter
SECURE_BROWSER_XSS_FILTER = True
# https://docs.djangoproject.com/en/dev/ref/settings/#x-frame-options
X_FRAME_OPTIONS = "DENY"
# EMAIL # EMAIL
# https://docs.djangoproject.com/en/2.2/ref/settings/#email
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
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
EMAIL_TIMEOUT = 5 EMAIL_TIMEOUT = 5
EMAIL_HOST = env("EMAIL_HOST", default="localhost")
EMAIL_HOST_USER = env("EMAIL_HOST_USER", default="")
EMAIL_HOST_PASSWORD = env("EMAIL_HOST_PASSWORD", default="")
EMAIL_PORT = env.int("EMAIL_PORT", 25)
EMAIL_SUBJECT_PREFIX = env(
"DJANGO_EMAIL_SUBJECT_PREFIX", default="[{{cookiecutter.project_name}}]"
)
DEFAULT_FROM_EMAIL = env(
"DJANGO_DEFAULT_FROM_EMAIL", default="{{cookiecutter.project_name}} <noreply@{{cookiecutter.domain_name}}>"
)
SERVER_EMAIL = env("DJANGO_SERVER_EMAIL", default=DEFAULT_FROM_EMAIL)
# ADMIN # ADMIN
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Django Admin URL. ADMIN_URL = env("DJANGO_ADMIN_URL", default="admin/")
ADMIN_URL = "admin/"
# https://docs.djangoproject.com/en/dev/ref/settings/#admins
ADMINS = [("""{{cookiecutter.author_name}}""", "{{cookiecutter.email}}")] ADMINS = [("""{{cookiecutter.author_name}}""", "{{cookiecutter.email}}")]
# https://docs.djangoproject.com/en/dev/ref/settings/#managers
MANAGERS = ADMINS MANAGERS = ADMINS
# LOGGING # LOGGING
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#logging # https://docs.djangoproject.com/en/dev/ref/settings/#logging
# ------------------------------------------------------------------------------
# See https://docs.djangoproject.com/en/dev/topics/logging for # See https://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration. # more details on how to customize your logging configuration.
LOGGING = { LOGGING = {
@ -250,34 +373,65 @@ LOGGING = {
} }
}, },
"root": {"level": "INFO", "handlers": ["console"]}, "root": {"level": "INFO", "handlers": ["console"]},
"loggers": {
"django.db.backends": {
"level": "ERROR",
"handlers": ["console"],
"propagate": False,
},
"django.security.DisallowedHost": {
"level": "ERROR",
"handlers": ["console"],
"propagate": False,
},
{%- if cookiecutter.use_sentry == 'y' %}
"sentry_sdk": { # Errors logged by Sentry's SDK itself
"level": "ERROR",
"handlers": ["console"],
"propagate": False,
},
{%- endif %}
},
} }
{% if cookiecutter.use_celery == 'y' -%} {%- if cookiecutter.use_sentry == 'y' %}
# Sentry
# ------------------------------------------------------------------------------
SENTRY_DSN = env("SENTRY_DSN")
SENTRY_LOG_LEVEL = env.int("DJANGO_SENTRY_LOG_LEVEL", logging.INFO)
sentry_logging = LoggingIntegration(
level=SENTRY_LOG_LEVEL, # Capture info and above as breadcrumbs
event_level=logging.ERROR, # Send errors as events
)
{%- if cookiecutter.use_celery == 'y' %}
sentry_sdk.init(
dsn=SENTRY_DSN,
integrations=[sentry_logging, DjangoIntegration(), CeleryIntegration()],
)
{%- else %}
sentry_sdk.init(dsn=SENTRY_DSN, integrations=[sentry_logging, DjangoIntegration()])
{% endif -%}{%- endif %}
{%- if cookiecutter.use_celery == 'y' %}
# Celery # Celery
# http://docs.celeryproject.org/en/latest/userguide/configuration.html
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
if USE_TZ: if USE_TZ:
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-timezone
CELERY_TIMEZONE = TIME_ZONE CELERY_TIMEZONE = TIME_ZONE
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-broker_url
CELERY_BROKER_URL = env("CELERY_BROKER_URL") CELERY_BROKER_URL = env("CELERY_BROKER_URL")
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-result_backend
CELERY_RESULT_BACKEND = CELERY_BROKER_URL CELERY_RESULT_BACKEND = CELERY_BROKER_URL
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-accept_content
CELERY_ACCEPT_CONTENT = ["json"] CELERY_ACCEPT_CONTENT = ["json"]
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-task_serializer
CELERY_TASK_SERIALIZER = "json" CELERY_TASK_SERIALIZER = "json"
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-result_serializer
CELERY_RESULT_SERIALIZER = "json" CELERY_RESULT_SERIALIZER = "json"
# 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
CELERY_TASK_TIME_LIMIT = 5 * 60 CELERY_TASK_TIME_LIMIT = 5 * 60
# 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
CELERY_TASK_SOFT_TIME_LIMIT = 60 CELERY_TASK_SOFT_TIME_LIMIT = 60
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#beat-scheduler
CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler" CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler"
{%- endif %} {%- endif %}
# django-allauth # django-allauth
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True) ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True)
@ -292,13 +446,6 @@ ACCOUNT_ADAPTER = "{{cookiecutter.project_slug}}.users.adapters.AccountAdapter"
# https://django-allauth.readthedocs.io/en/latest/configuration.html # https://django-allauth.readthedocs.io/en/latest/configuration.html
SOCIALACCOUNT_ADAPTER = "{{cookiecutter.project_slug}}.users.adapters.SocialAccountAdapter" SOCIALACCOUNT_ADAPTER = "{{cookiecutter.project_slug}}.users.adapters.SocialAccountAdapter"
{% if cookiecutter.use_compressor == 'y' -%}
# django-compressor
# ------------------------------------------------------------------------------
# https://django-compressor.readthedocs.io/en/latest/quickstart/#installation
INSTALLED_APPS += ["compressor"]
STATICFILES_FINDERS += ["compressor.finders.CompressorFinder"]
{%- endif %}
# Your stuff... # Your stuff...
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -25,12 +25,9 @@ CACHES = {
# EMAIL # EMAIL
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
{% if cookiecutter.use_mailhog == 'y' and cookiecutter.use_docker == 'y' -%} {% if cookiecutter.use_mailhog == 'y' -%}
# https://docs.djangoproject.com/en/dev/ref/settings/#email-host # https://docs.djangoproject.com/en/dev/ref/settings/#email-host
EMAIL_HOST = env("EMAIL_HOST", default="mailhog") EMAIL_HOST = env("EMAIL_HOST", default="mailhog")
{%- elif cookiecutter.use_mailhog == 'y' and cookiecutter.use_docker == 'n' -%}
# https://docs.djangoproject.com/en/dev/ref/settings/#email-host
EMAIL_HOST = "localhost"
{%- else -%} {%- else -%}
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend # https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
EMAIL_BACKEND = env( EMAIL_BACKEND = env(
@ -55,13 +52,11 @@ DEBUG_TOOLBAR_CONFIG = {
} }
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#internal-ips # https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#internal-ips
INTERNAL_IPS = ["127.0.0.1", "10.0.2.2"] INTERNAL_IPS = ["127.0.0.1", "10.0.2.2"]
{% if cookiecutter.use_docker == 'y' -%}
if env("USE_DOCKER") == "yes": 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 += [ip[:-1] + "1" for ip in ips]
{%- endif %}
# django-extensions # django-extensions
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -71,10 +66,8 @@ INSTALLED_APPS += ["django_extensions"] # noqa F405
# Celery # Celery
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
{% if cookiecutter.use_docker == 'n' -%}
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-always-eager # http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-always-eager
CELERY_TASK_ALWAYS_EAGER = True CELERY_TASK_ALWAYS_EAGER = True
{%- endif %}
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-eager-propagates # http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-eager-propagates
CELERY_TASK_EAGER_PROPAGATES = True CELERY_TASK_EAGER_PROPAGATES = True

View File

@ -0,0 +1,15 @@
from .base import * # noqa
# TEMPLATES
# https://docs.djangoproject.com/en/dev/ref/settings/#templates
# ------------------------------------------------------------------------------
TEMPLATES[0]["OPTIONS"]["loaders"] = [ # noqa F405
(
"django.template.loaders.cached.Loader",
[
"django.template.loaders.filesystem.Loader",
"django.template.loaders.app_directories.Loader",
],
)
]

View File

@ -1,10 +1,3 @@
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
@import "custom_bootstrap_vars";
@import "bootstrap";
{% endif %}
// project specific CSS goes here // project specific CSS goes here
//////////////////////////////// ////////////////////////////////

View File

@ -16,15 +16,13 @@
<link rel="icon" href="{% static 'images/favicons/favicon.ico' %}"> <link rel="icon" href="{% static 'images/favicons/favicon.ico' %}">
{% block css %} {% block css %}
{% endraw %}{% if cookiecutter.custom_bootstrap_compilation == "n" %}{% raw %}
<!-- Latest compiled and minified Bootstrap CSS --> <!-- Latest compiled and minified Bootstrap CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
{% endraw %}{% endif %}{% raw %}
<!-- Your stuff: Third-party CSS libraries go here --> <!-- Your stuff: Third-party CSS libraries go here -->
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress css %}{% endraw %}{% endif %}{% raw %} {% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress css %}{% endraw %}{% endif %}{% raw %}
<!-- This file stores project-specific CSS --> <!-- This file stores project-specific CSS -->
{% endraw %}{% if cookiecutter.js_task_runner == "Gulp" and cookiecutter.use_compressor == "n" %}{% raw %} {% endraw %}{% if cookiecutter.use_compressor == "n" %}{% raw %}
<link href="{% static 'css/project.min.css' %}" rel="stylesheet"> <link href="{% static 'css/project.min.css' %}" rel="stylesheet">
{% endraw %}{% else %}{% raw %} {% endraw %}{% else %}{% raw %}
<link href="{% static 'css/project.css' %}" rel="stylesheet"> <link href="{% static 'css/project.css' %}" rel="stylesheet">
@ -96,22 +94,19 @@
================================================== --> ================================================== -->
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
{% block javascript %} {% block javascript %}
{% endraw %}{% if cookiecutter.custom_bootstrap_compilation == "y" and cookiecutter.js_task_runner == "Gulp" %}{% raw %}
<!-- Vendor dependencies bundled as one file--> <!-- Vendor dependencies bundled as one file-->
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress js %}{% endraw %}{% endif %}{% raw %} {% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress js %}{% endraw %}{% endif %}{% raw %}
<script src="{% static 'js/vendors.js' %}"></script> <script src="{% static 'js/vendors.js' %}"></script>
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% endcompress %}{% endraw %}{% endif %}{% raw %} {% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% endcompress %}{% endraw %}{% endif %}{% raw %}
{% endraw %}{% else %}{% raw %}
<!-- Bootstrap JS and its dependencies--> <!-- Bootstrap JS and its dependencies-->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<!-- Your stuff: Third-party javascript libraries go here --> <!-- Your stuff: Third-party javascript libraries go here -->
{% endraw %}{% endif %}{% raw %}
<!-- place project specific Javascript in this file --> <!-- place project specific Javascript in this file -->
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress js %}{% endraw %}{% endif %}{% raw %} {% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress js %}{% endraw %}{% endif %}{% raw %}
<script src="{% static 'js/project.js' %}"></script> <script src="{% static 'js/project.js' %}"></script>
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% endcompress %}{% endraw %}{% endif %}{% raw %} {% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% endcompress %}{% endraw %}{% endif %}{% raw %}