mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-08-08 14:04:52 +03:00
Merge branch 'master' into master
This commit is contained in:
commit
3e0bc83bfe
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -226,3 +226,5 @@ pip-selfcheck.json
|
||||||
# to 'run' anything within it since any particular cookiecutter
|
# to 'run' anything within it since any particular cookiecutter
|
||||||
# is declarative by nature.
|
# is declarative by nature.
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
.pytest_cache/
|
||||||
|
|
|
@ -13,15 +13,6 @@ env:
|
||||||
- TOX_ENV=py36
|
- TOX_ENV=py36
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- sudo sh -c 'echo "deb https://apt.dockerproject.org/repo ubuntu-precise main" > /etc/apt/sources.list.d/docker.list'
|
|
||||||
- sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
|
|
||||||
- sudo apt-get update
|
|
||||||
- sudo apt-key update
|
|
||||||
- sudo apt-get --force-yes -qqy -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install docker-engine=1.11.1-0~precise
|
|
||||||
- sudo rm /usr/local/bin/docker-compose
|
|
||||||
- curl -L https://github.com/docker/compose/releases/download/1.7.0/docker-compose-`uname -s`-`uname -m` > docker-compose
|
|
||||||
- chmod +x docker-compose
|
|
||||||
- sudo mv docker-compose /usr/local/bin
|
|
||||||
- docker-compose -v
|
- docker-compose -v
|
||||||
- docker -v
|
- docker -v
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
All enhancements and patches to Cookiecutter Django will be documented in this file.
|
All enhancements and patches to Cookiecutter Django will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [2018-02-16]
|
||||||
|
### Changed
|
||||||
|
- Upgraded to Django 2.0 (@epicwhale)
|
||||||
|
|
||||||
## [2018-01-15]
|
## [2018-01-15]
|
||||||
### Changed
|
### Changed
|
||||||
- Removed Elastic Beanstalk support (@pydanny)
|
- Removed Elastic Beanstalk support (@pydanny)
|
||||||
|
|
|
@ -44,6 +44,7 @@ Listed in alphabetical order.
|
||||||
Aaron Eikenberry `@aeikenberry`_
|
Aaron Eikenberry `@aeikenberry`_
|
||||||
Adam Bogdał `@bogdal`_
|
Adam Bogdał `@bogdal`_
|
||||||
Adam Dobrawy `@ad-m`_
|
Adam Dobrawy `@ad-m`_
|
||||||
|
Adam Steele `@adammsteele`
|
||||||
Agam Dua
|
Agam Dua
|
||||||
Alberto Sanchez `@alb3rto`_
|
Alberto Sanchez `@alb3rto`_
|
||||||
Alex Tsai `@caffodian`_
|
Alex Tsai `@caffodian`_
|
||||||
|
@ -88,6 +89,7 @@ Listed in alphabetical order.
|
||||||
Dong Huynh `@trungdong`_
|
Dong Huynh `@trungdong`_
|
||||||
Emanuel Calso `@bloodpet`_ @bloodpet
|
Emanuel Calso `@bloodpet`_ @bloodpet
|
||||||
Eraldo Energy `@eraldo`_
|
Eraldo Energy `@eraldo`_
|
||||||
|
Eric Groom `@ericgroom`_
|
||||||
Eyad Al Sibai `@eyadsibai`_
|
Eyad Al Sibai `@eyadsibai`_
|
||||||
Felipe Arruda `@arruda`_
|
Felipe Arruda `@arruda`_
|
||||||
Garry Cairns `@garry-cairns`_
|
Garry Cairns `@garry-cairns`_
|
||||||
|
@ -159,6 +161,7 @@ Listed in alphabetical order.
|
||||||
|
|
||||||
.. _@a7p: https://github.com/a7p
|
.. _@a7p: https://github.com/a7p
|
||||||
.. _@ad-m: https://github.com/ad-m
|
.. _@ad-m: https://github.com/ad-m
|
||||||
|
.. _@adammsteele: https://github.com/adammsteele
|
||||||
.. _@aeikenberry: https://github.com/aeikenberry
|
.. _@aeikenberry: https://github.com/aeikenberry
|
||||||
.. _@alb3rto: https://github.com/alb3rto
|
.. _@alb3rto: https://github.com/alb3rto
|
||||||
.. _@ameistad: https://github.com/ameistad
|
.. _@ameistad: https://github.com/ameistad
|
||||||
|
|
17
README.rst
17
README.rst
|
@ -41,7 +41,7 @@ Features
|
||||||
* For Django 2.0
|
* For Django 2.0
|
||||||
* Works with Python 3.6
|
* Works with Python 3.6
|
||||||
* Renders Django projects with 100% starting test coverage
|
* Renders Django projects with 100% starting test coverage
|
||||||
* Twitter Bootstrap_ v4.0.0 - beta 1 (`maintained Foundation fork`_ also available)
|
* Twitter Bootstrap_ v4.0.0 (`maintained Foundation fork`_ also available)
|
||||||
* 12-Factor_ based settings via django-environ_
|
* 12-Factor_ based settings via django-environ_
|
||||||
* Secure by default. We believe in SSL.
|
* Secure by default. We believe in SSL.
|
||||||
* Optimized development and production settings
|
* Optimized development and production settings
|
||||||
|
@ -111,7 +111,7 @@ Two Scoops of Django 1.11
|
||||||
:name: Two Scoops of Django 1.11 Cover
|
:name: Two Scoops of Django 1.11 Cover
|
||||||
:align: center
|
:align: center
|
||||||
:alt: Two Scoops of Django
|
:alt: Two Scoops of Django
|
||||||
:target: http://twoscoopspress.org/products/two-scoops-of-django-1-11
|
:target: http://twoscoopspress.com/products/two-scoops-of-django-1-11
|
||||||
|
|
||||||
Two Scoops of Django is the best dessert-themed Django reference in the universe
|
Two Scoops of Django is the best dessert-themed Django reference in the universe
|
||||||
|
|
||||||
|
@ -171,12 +171,13 @@ Answer the prompts with your own desired options_. For example::
|
||||||
use_heroku [n]: y
|
use_heroku [n]: y
|
||||||
use_compressor [n]: y
|
use_compressor [n]: y
|
||||||
Select postgresql_version:
|
Select postgresql_version:
|
||||||
1 - 10
|
1 - 10.3
|
||||||
2 - 9.6
|
2 - 10.2
|
||||||
3 - 9.5
|
3 - 10.1
|
||||||
4 - 9.4
|
4 - 9.6
|
||||||
5 - 9.3
|
5 - 9.5
|
||||||
6 - 9.2
|
6 - 9.4
|
||||||
|
7 - 9.3
|
||||||
Choose from 1, 2, 3, 4 [1]: 1
|
Choose from 1, 2, 3, 4 [1]: 1
|
||||||
Select js_task_runner:
|
Select js_task_runner:
|
||||||
1 - Gulp
|
1 - Gulp
|
||||||
|
|
|
@ -1,24 +1,43 @@
|
||||||
{
|
{
|
||||||
"project_name": "Project Name",
|
"project_name": "My Awesome Project",
|
||||||
"project_slug": "{{ cookiecutter.project_name.lower()|replace(' ', '_')|replace('-', '_') }}",
|
"project_slug": "{{ cookiecutter.project_name.lower()|replace(' ', '_')|replace('-', '_') }}",
|
||||||
"author_name": "Daniel Roy Greenfeld",
|
"description": "Behold My Awesome Project!",
|
||||||
"email": "you@example.com",
|
"author_name": "Daniel Roy Greenfeld",
|
||||||
"description": "A short description of the project.",
|
"email": "{{ cookiecutter.author_name.lower()|replace(' ', '-') }}@example.com",
|
||||||
"domain_name": "example.com",
|
"domain_name": "example.com",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"timezone": "UTC",
|
"open_source_license": [
|
||||||
"use_whitenoise": "y",
|
"MIT",
|
||||||
"use_celery": "n",
|
"BSD",
|
||||||
"use_mailhog": "n",
|
"GPLv3",
|
||||||
"use_sentry_for_error_reporting": "y",
|
"Apache Software License 2.0",
|
||||||
"use_opbeat": "n",
|
"Not open source"
|
||||||
"use_pycharm": "n",
|
],
|
||||||
"windows": "n",
|
"timezone": "UTC",
|
||||||
"use_docker": "n",
|
"windows": "n",
|
||||||
"use_heroku": "n",
|
"use_pycharm": "n",
|
||||||
"use_compressor": "n",
|
"use_docker": "n",
|
||||||
"postgresql_version": ["10", "9.6", "9.5", "9.4", "9.3", "9.2"],
|
"postgresql_version": [
|
||||||
"js_task_runner": ["Gulp", "Grunt", "None"],
|
"10.3",
|
||||||
"custom_bootstrap_compilation": "n",
|
"10.2",
|
||||||
"open_source_license": ["MIT", "BSD", "GPLv3", "Apache Software License 2.0", "Not open source"]
|
"10.1",
|
||||||
|
"9.6",
|
||||||
|
"9.5",
|
||||||
|
"9.4",
|
||||||
|
"9.3"
|
||||||
|
],
|
||||||
|
"js_task_runner": [
|
||||||
|
"None",
|
||||||
|
"Gulp",
|
||||||
|
"Grunt"
|
||||||
|
],
|
||||||
|
"custom_bootstrap_compilation": "n",
|
||||||
|
"use_compressor": "n",
|
||||||
|
"use_celery": "n",
|
||||||
|
"use_mailhog": "n",
|
||||||
|
"use_sentry_for_error_reporting": "y",
|
||||||
|
"use_opbeat": "n",
|
||||||
|
"use_whitenoise": "y",
|
||||||
|
"use_heroku": "n",
|
||||||
|
"use_travisci": "n"
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,9 @@ Run these commands to deploy the project to Heroku:
|
||||||
heroku addons:create heroku-redis:hobby-dev
|
heroku addons:create heroku-redis:hobby-dev
|
||||||
heroku addons:create mailgun
|
heroku addons:create mailgun
|
||||||
|
|
||||||
heroku config:set DJANGO_ADMIN_URL="$(openssl rand -base64 32)"
|
heroku config:set WEB_CONCURRENCY=4
|
||||||
|
# Generating a 32 character-long random string without any of the visually similiar characters "IOl01":
|
||||||
|
heroku config:set DJANGO_ADMIN_URL="^$(openssl rand -base64 4096 | tr -dc 'A-HJ-NP-Za-km-z2-9' | head -c 32)/"
|
||||||
heroku config:set DJANGO_SECRET_KEY="$(openssl rand -base64 64)"
|
heroku config:set DJANGO_SECRET_KEY="$(openssl rand -base64 64)"
|
||||||
heroku config:set DJANGO_SETTINGS_MODULE='config.settings.production'
|
heroku config:set DJANGO_SETTINGS_MODULE='config.settings.production'
|
||||||
heroku config:set DJANGO_ALLOWED_HOSTS='.herokuapp.com'
|
heroku config:set DJANGO_ALLOWED_HOSTS='.herokuapp.com'
|
||||||
|
@ -25,12 +27,10 @@ Run these commands to deploy the project to Heroku:
|
||||||
heroku config:set DJANGO_AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_ACCESS_KEY_HERE
|
heroku config:set DJANGO_AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_ACCESS_KEY_HERE
|
||||||
heroku config:set DJANGO_AWS_STORAGE_BUCKET_NAME=YOUR_AWS_S3_BUCKET_NAME_HERE
|
heroku config:set DJANGO_AWS_STORAGE_BUCKET_NAME=YOUR_AWS_S3_BUCKET_NAME_HERE
|
||||||
|
|
||||||
heroku config:set DJANGO_MAILGUN_SERVER_NAME=YOUR_MALGUN_SERVER
|
# This is to be set only if you're using Sentry:
|
||||||
heroku config:set DJANGO_MAILGUN_API_KEY=YOUR_MAILGUN_API_KEY
|
heroku config:set DJANGO_SENTRY_DSN=YOUR_SENTRY_DSN
|
||||||
heroku config:set MAILGUN_SENDER_DOMAIN=YOUR_MAILGUN_SENDER_DOMAIN
|
|
||||||
|
|
||||||
heroku config:set PYTHONHASHSEED=random
|
heroku config:set PYTHONHASHSEED=random
|
||||||
heroku config:set DJANGO_ADMIN_URL=\^somelocation/
|
|
||||||
|
|
||||||
git push heroku master
|
git push heroku master
|
||||||
heroku run python manage.py migrate
|
heroku run python manage.py migrate
|
||||||
|
|
|
@ -63,13 +63,13 @@ Add these exports
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
|
export WEB_CONCURRENCY=4
|
||||||
export DJANGO_SETTINGS_MODULE='config.settings.production'
|
export DJANGO_SETTINGS_MODULE='config.settings.production'
|
||||||
export DJANGO_SECRET_KEY='<secret key goes here>'
|
export DJANGO_SECRET_KEY='<secret key goes here>'
|
||||||
export DJANGO_ALLOWED_HOSTS='<www.your-domain.com>'
|
export DJANGO_ALLOWED_HOSTS='<www.your-domain.com>'
|
||||||
export DJANGO_ADMIN_URL='<not admin/>'
|
export DJANGO_ADMIN_URL='<not admin/>'
|
||||||
export DJANGO_MAILGUN_API_KEY='<mailgun key>'
|
export MAILGUN_API_KEY='<mailgun key>'
|
||||||
export DJANGO_MAILGUN_SERVER_NAME='<mailgun server name>'
|
export MAILGUN_DOMAIN='<mailgun sender domain (e.g. mg.yourdomain.com)>'
|
||||||
export MAILGUN_SENDER_DOMAIN='<mailgun sender domain (e.g. mg.yourdomain.com)>'
|
|
||||||
export DJANGO_AWS_ACCESS_KEY_ID=
|
export DJANGO_AWS_ACCESS_KEY_ID=
|
||||||
export DJANGO_AWS_SECRET_ACCESS_KEY=
|
export DJANGO_AWS_SECRET_ACCESS_KEY=
|
||||||
export DJANGO_AWS_STORAGE_BUCKET_NAME=
|
export DJANGO_AWS_STORAGE_BUCKET_NAME=
|
||||||
|
@ -138,9 +138,8 @@ Click through to the **WSGI configuration file** link (near the top) and edit th
|
||||||
os.environ['DJANGO_SECRET_KEY'] = '<as above>'
|
os.environ['DJANGO_SECRET_KEY'] = '<as above>'
|
||||||
os.environ['DJANGO_ALLOWED_HOSTS'] = '<as above>'
|
os.environ['DJANGO_ALLOWED_HOSTS'] = '<as above>'
|
||||||
os.environ['DJANGO_ADMIN_URL'] = '<as above>'
|
os.environ['DJANGO_ADMIN_URL'] = '<as above>'
|
||||||
os.environ['DJANGO_MAILGUN_API_KEY'] = '<as above>'
|
os.environ['MAILGUN_API_KEY'] = '<as above>'
|
||||||
os.environ['DJANGO_MAILGUN_SERVER_NAME'] = '<as above>'
|
os.environ['MAILGUN_DOMAIN'] = '<as above>'
|
||||||
os.environ['MAILGUN_SENDER_DOMAIN'] = '<as above>'
|
|
||||||
os.environ['DJANGO_AWS_ACCESS_KEY_ID'] = ''
|
os.environ['DJANGO_AWS_ACCESS_KEY_ID'] = ''
|
||||||
os.environ['DJANGO_AWS_SECRET_ACCESS_KEY'] = ''
|
os.environ['DJANGO_AWS_SECRET_ACCESS_KEY'] = ''
|
||||||
os.environ['DJANGO_AWS_STORAGE_BUCKET_NAME'] = ''
|
os.environ['DJANGO_AWS_STORAGE_BUCKET_NAME'] = ''
|
||||||
|
|
|
@ -42,6 +42,13 @@ You will probably also need to setup the Mail backend, for example by adding a `
|
||||||
.. _sentry.io: https://sentry.io/welcome
|
.. _sentry.io: https://sentry.io/welcome
|
||||||
.. _Mailgun: https://mailgun.com
|
.. _Mailgun: https://mailgun.com
|
||||||
|
|
||||||
|
Optional: Use AWS IAM Role for EC2 instance
|
||||||
|
------------------------------------
|
||||||
|
If you are deploying to AWS, you can use the IAM role to substitute AWS credentials, after which it's safe to remove the `AWS_ACCESS_KEY_ID` AND `AWS_SECRET_ACCESS_KEY` from the `.env`. To do it, create an `IAM role`_ and `attach`_ it to the existing EC2 instance or create a new EC2 instance with that role. The role should assume a minimum permission of `AmazonS3FullAccess`.
|
||||||
|
|
||||||
|
.. _IAM role: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html
|
||||||
|
.. _attach: https://aws.amazon.com/blogs/security/easily-replace-or-attach-an-iam-role-to-an-existing-ec2-instance-by-using-the-ec2-console/
|
||||||
|
|
||||||
HTTPS is on by default
|
HTTPS is on by default
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ If you don't already have it, install `compass` (doesn't hurt if you run this co
|
||||||
|
|
||||||
Now you just need::
|
Now you just need::
|
||||||
|
|
||||||
$ grunt serve
|
$ npm run dev
|
||||||
|
|
||||||
The base app will now run as it would with the usual ``manage.py runserver`` but with live reloading and Sass compilation enabled.
|
The base app will now run as it would with the usual ``manage.py runserver`` but with live reloading and Sass compilation enabled.
|
||||||
|
|
||||||
|
|
|
@ -1,69 +1,61 @@
|
||||||
Project Generation Options
|
Project Generation Options
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
project_name [project_name]:
|
project_name [My Awesome Project]:
|
||||||
Your human-readable project name, including any capitalization or spaces.
|
Your project's human-readable name, capitals and spaces allowed.
|
||||||
|
|
||||||
project_slug [project_name]:
|
project_slug [my_awesome_project]:
|
||||||
The slug of your project, without dashes or spaces. Used to name your repo
|
Your project's slug without dashes or spaces. Used to name your repo
|
||||||
and in other places where a Python-importable version of your project name
|
and in other places where a Python-importable version of your project name
|
||||||
is needed.
|
is needed.
|
||||||
|
|
||||||
author_name [Your Name]:
|
description [Behold My Awesome Project!]
|
||||||
You! This goes into places like the LICENSE file.
|
Describes your project and gets used in places like `README.rst` and such.
|
||||||
|
|
||||||
email [Your email]:
|
author_name [Daniel Roy Greenfeld]:
|
||||||
Your email address.
|
This is you! The value goes into places like `LICENSE` and such.
|
||||||
|
|
||||||
description [A short description of the project.]
|
email [daniel-roy-greenfeld@example.com]:
|
||||||
Used in the generated README.rst and other places.
|
The email address you want to identify yourself in the project.
|
||||||
|
|
||||||
domain_name [example.com]
|
domain_name [example.com]
|
||||||
Whatever domain name you plan to use for your project when it goes live.
|
The domain name you plan to use for your project once it goes live.
|
||||||
|
Note that it can be safely changed later on whenever you need to.
|
||||||
|
|
||||||
version [0.1.0]
|
version [0.1.0]
|
||||||
The starting version number for your project.
|
The version of the project at its inception.
|
||||||
|
|
||||||
|
open_source_license [1]
|
||||||
|
A software license for the project. The choices are:
|
||||||
|
|
||||||
|
1. MIT_
|
||||||
|
2. BSD_
|
||||||
|
3. GPLv3_
|
||||||
|
4. `Apache Software License 2.0`_
|
||||||
|
5. Not open source
|
||||||
|
|
||||||
timezone [UTC]
|
timezone [UTC]
|
||||||
Used in the base settings file for the `TIME_ZONE` value.
|
The value to be used for the `TIME_ZONE` setting of the project.
|
||||||
|
|
||||||
use_whitenoise [y]
|
|
||||||
Whether to use WhiteNoise_ for static file serving.
|
|
||||||
|
|
||||||
use_celery [n]
|
|
||||||
Whether to use Celery_. This gives you the ability to use distributed task
|
|
||||||
queues in your project.
|
|
||||||
|
|
||||||
use_mailhog [n]
|
|
||||||
Whether to use MailHog_. MailHog is a tool that simulates email receiving
|
|
||||||
for development purposes. It runs a simple SMTP server which catches
|
|
||||||
any message sent to it. Messages are displayed in a web interface which
|
|
||||||
runs at ``http://localhost:8025/`` You need to download the MailHog
|
|
||||||
executable for your operating system, see the 'Developing Locally' docs
|
|
||||||
for instructions.
|
|
||||||
|
|
||||||
use_sentry_for_error_reporting [n]
|
|
||||||
Whether to use Sentry_ to log errors from your project.
|
|
||||||
|
|
||||||
use_opbeat [n]
|
|
||||||
Whether to use Opbeat_ for preformance monitoring and code optimization.
|
|
||||||
|
|
||||||
use_pycharm [n]
|
|
||||||
Adds support for developing in PyCharm_ with a preconfigured .idea directory.
|
|
||||||
|
|
||||||
windows [n]
|
windows [n]
|
||||||
Whether you'll be developing on Windows.
|
Indicates whether the project should be configured for development on Windows.
|
||||||
|
|
||||||
|
use_pycharm [n]
|
||||||
|
Indicates whether the project should be configured for development with PyCharm_.
|
||||||
|
|
||||||
use_docker [y]
|
use_docker [y]
|
||||||
Whether to use Docker_, separating the app and database into separate
|
Indicates whether the project should be configured to use Docker_ and `Docker Compose`_.
|
||||||
containers.
|
|
||||||
|
|
||||||
use_heroku [n]
|
postgresql_version [1]
|
||||||
Add configuration to deploy the application to a Heroku_ instance.
|
Select a PostgreSQL_ version to use. The choices are:
|
||||||
|
|
||||||
use_compressor [n]
|
1. 10.3
|
||||||
Use `Django Compressor`_ to minify and combine rendered JavaScript and CSS
|
2. 10.2
|
||||||
into cachable static resources.
|
3. 10.1
|
||||||
|
4. 9.6
|
||||||
|
5. 9.5
|
||||||
|
6. 9.4
|
||||||
|
7. 9.3
|
||||||
|
|
||||||
js_task_runner [1]
|
js_task_runner [1]
|
||||||
Select a JavaScript task runner. The choices are:
|
Select a JavaScript task runner. The choices are:
|
||||||
|
@ -73,36 +65,63 @@ js_task_runner [1]
|
||||||
3. None
|
3. None
|
||||||
|
|
||||||
custom_bootstrap_compilation [n]
|
custom_bootstrap_compilation [n]
|
||||||
Scaffold out recompiling Bootstrap as as task, with Gulp_ or Grunt_.
|
Indicates whether the project should support Bootstrap recompilation
|
||||||
Useful for letting you change Bootstrap variables in real time.
|
via the selected JavaScript task runner's task. This can be useful
|
||||||
Consult project README for more details.
|
for real-time Bootstrap variable alteration.
|
||||||
|
|
||||||
open_source_license [1]
|
use_compressor [n]
|
||||||
Select a software license for the project. The choices are:
|
Indicates whether the project should be configured to use `Django Compressor`_.
|
||||||
|
|
||||||
1. MIT_
|
use_celery [n]
|
||||||
2. BSD_
|
Indicates whether the project should be configured to use Celery_.
|
||||||
3. GPLv3_
|
|
||||||
4. `Apache Software License 2.0`_
|
use_mailhog [n]
|
||||||
5. Not open source
|
Indicates whether the project should be configured to use MailHog_.
|
||||||
|
|
||||||
|
use_sentry_for_error_reporting [n]
|
||||||
|
Indicates whether the project should be configured to use Sentry_.
|
||||||
|
|
||||||
|
use_opbeat [n]
|
||||||
|
Indicates whether the project should be configured to use Opbeat_.
|
||||||
|
|
||||||
|
use_whitenoise [y]
|
||||||
|
Indicates whether the project should be configured to use WhiteNoise_.
|
||||||
|
|
||||||
|
use_heroku [n]
|
||||||
|
Indicates whether the project should be configured so as to be deployable
|
||||||
|
to Heroku_.
|
||||||
|
|
||||||
|
use_travisci [n]
|
||||||
|
Indicates whether the project should be configured to use `Travis CI`_.
|
||||||
|
|
||||||
**NOTE:** *If you choose to use Docker, selecting a JavaScript task runner is
|
|
||||||
not supported out of the box.*
|
|
||||||
|
|
||||||
.. _WhiteNoise: https://github.com/evansd/whitenoise
|
|
||||||
.. _Celery: https://github.com/celery/celery
|
|
||||||
.. _MailHog: https://github.com/mailhog/MailHog
|
|
||||||
.. _Sentry: https://github.com/getsentry/sentry
|
|
||||||
.. _Opbeat: https://github.com/opbeat/opbeat_python
|
|
||||||
.. _PyCharm: https://www.jetbrains.com/pycharm/
|
|
||||||
.. _Docker: https://github.com/docker/docker
|
|
||||||
.. _Heroku: https://github.com/heroku/heroku-buildpack-python
|
|
||||||
.. _Django Compressor: https://github.com/django-compressor/django-compressor
|
|
||||||
.. _Gulp: https://github.com/gulpjs/gulp
|
|
||||||
.. _Grunt: https://github.com/gruntjs/grunt
|
|
||||||
.. _Webpack: https://github.com/webpack/webpack
|
|
||||||
.. _Let's Encrypt: https://github.com/certbot/certbot
|
|
||||||
.. _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
|
||||||
.. _Apache Software License 2.0: http://www.apache.org/licenses/LICENSE-2.0
|
.. _Apache Software License 2.0: http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
.. _PyCharm: https://www.jetbrains.com/pycharm/
|
||||||
|
|
||||||
|
.. _Docker: https://github.com/docker/docker
|
||||||
|
.. _Docker Compose: https://docs.docker.com/compose/
|
||||||
|
|
||||||
|
.. _PostgreSQL: https://www.postgresql.org/docs/
|
||||||
|
|
||||||
|
.. _Gulp: https://github.com/gulpjs/gulp
|
||||||
|
.. _Grunt: https://github.com/gruntjs/grunt
|
||||||
|
|
||||||
|
.. _Django Compressor: https://github.com/django-compressor/django-compressor
|
||||||
|
|
||||||
|
.. _Celery: https://github.com/celery/celery
|
||||||
|
|
||||||
|
.. _MailHog: https://github.com/mailhog/MailHog
|
||||||
|
|
||||||
|
.. _Sentry: https://github.com/getsentry/sentry
|
||||||
|
|
||||||
|
.. _Opbeat: https://github.com/opbeat/opbeat_python
|
||||||
|
|
||||||
|
.. _WhiteNoise: https://github.com/evansd/whitenoise
|
||||||
|
|
||||||
|
.. _Heroku: https://github.com/heroku/heroku-buildpack-python
|
||||||
|
|
||||||
|
.. _Travis CI: https://travis-ci.org/
|
||||||
|
|
|
@ -47,9 +47,8 @@ DJANGO_AWS_STORAGE_BUCKET_NAME AWS_STORAGE_BUCKET_NAME n/a
|
||||||
DJANGO_SENTRY_DSN SENTRY_DSN n/a raises error
|
DJANGO_SENTRY_DSN SENTRY_DSN n/a raises error
|
||||||
DJANGO_SENTRY_CLIENT SENTRY_CLIENT n/a raven.contrib.django.raven_compat.DjangoClient
|
DJANGO_SENTRY_CLIENT SENTRY_CLIENT n/a raven.contrib.django.raven_compat.DjangoClient
|
||||||
DJANGO_SENTRY_LOG_LEVEL SENTRY_LOG_LEVEL n/a logging.INFO
|
DJANGO_SENTRY_LOG_LEVEL SENTRY_LOG_LEVEL n/a logging.INFO
|
||||||
DJANGO_MAILGUN_API_KEY MAILGUN_ACCESS_KEY n/a raises error
|
MAILGUN_API_KEY MAILGUN_ACCESS_KEY n/a raises error
|
||||||
DJANGO_MAILGUN_SERVER_NAME MAILGUN_SERVER_NAME n/a raises error
|
MAILGUN_DOMAIN MAILGUN_SENDER_DOMAIN n/a raises error
|
||||||
MAILGUN_SENDER_DOMAIN MAILGUN_SENDER_DOMAIN n/a raises error
|
|
||||||
NEW_RELIC_APP_NAME NEW_RELIC_APP_NAME n/a raises error
|
NEW_RELIC_APP_NAME NEW_RELIC_APP_NAME n/a raises error
|
||||||
NEW_RELIC_LICENSE_KEY NEW_RELIC_LICENSE_KEY n/a raises error
|
NEW_RELIC_LICENSE_KEY NEW_RELIC_LICENSE_KEY n/a raises error
|
||||||
DJANGO_OPBEAT_APP_ID OPBEAT['APP_ID'] n/a raises error
|
DJANGO_OPBEAT_APP_ID OPBEAT['APP_ID'] n/a raises error
|
||||||
|
|
|
@ -25,11 +25,6 @@ except NotImplementedError:
|
||||||
PROJECT_DIR_PATH = os.path.realpath(os.path.curdir)
|
PROJECT_DIR_PATH = os.path.realpath(os.path.curdir)
|
||||||
|
|
||||||
|
|
||||||
def remove_file(file_path):
|
|
||||||
if os.path.exists(file_path):
|
|
||||||
os.remove(file_path)
|
|
||||||
|
|
||||||
|
|
||||||
def remove_open_source_project_only_files():
|
def remove_open_source_project_only_files():
|
||||||
file_names = [
|
file_names = [
|
||||||
'CONTRIBUTORS.txt',
|
'CONTRIBUTORS.txt',
|
||||||
|
@ -72,22 +67,14 @@ def remove_heroku_files():
|
||||||
file_names = [
|
file_names = [
|
||||||
'Procfile',
|
'Procfile',
|
||||||
'runtime.txt',
|
'runtime.txt',
|
||||||
|
'requirements.txt',
|
||||||
]
|
]
|
||||||
for file_name in file_names:
|
for file_name in file_names:
|
||||||
remove_file(os.path.join(PROJECT_DIR_PATH, file_name))
|
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
||||||
|
|
||||||
|
|
||||||
def remove_paas_files():
|
def remove_dotenv_file():
|
||||||
none_paas_files_left = True
|
os.remove(os.path.join(PROJECT_DIR_PATH, '.env'))
|
||||||
|
|
||||||
if '{{ cookiecutter.use_heroku }}'.lower() == 'n':
|
|
||||||
remove_heroku_files()
|
|
||||||
none_paas_files_left &= True
|
|
||||||
else:
|
|
||||||
none_paas_files_left &= False
|
|
||||||
|
|
||||||
if none_paas_files_left:
|
|
||||||
remove_file(os.path.join(PROJECT_DIR_PATH, 'requirements.txt'))
|
|
||||||
|
|
||||||
|
|
||||||
def remove_grunt_files():
|
def remove_grunt_files():
|
||||||
|
@ -118,6 +105,10 @@ def remove_celery_app():
|
||||||
shutil.rmtree(os.path.join(PROJECT_DIR_PATH, '{{ cookiecutter.project_slug }}', 'taskapp'))
|
shutil.rmtree(os.path.join(PROJECT_DIR_PATH, '{{ cookiecutter.project_slug }}', 'taskapp'))
|
||||||
|
|
||||||
|
|
||||||
|
def remove_dottravisyml_file():
|
||||||
|
os.remove(os.path.join(PROJECT_DIR_PATH, '.travis.yml'))
|
||||||
|
|
||||||
|
|
||||||
def append_to_project_gitignore(path):
|
def append_to_project_gitignore(path):
|
||||||
gitignore_file_path = os.path.join(PROJECT_DIR_PATH, '.gitignore')
|
gitignore_file_path = os.path.join(PROJECT_DIR_PATH, '.gitignore')
|
||||||
with open(gitignore_file_path, 'a') as gitignore_file:
|
with open(gitignore_file_path, 'a') as gitignore_file:
|
||||||
|
@ -241,7 +232,7 @@ def main():
|
||||||
|
|
||||||
if '{{ cookiecutter.open_source_license }}' == 'Not open source':
|
if '{{ cookiecutter.open_source_license }}' == 'Not open source':
|
||||||
remove_open_source_project_only_files()
|
remove_open_source_project_only_files()
|
||||||
elif '{{ cookiecutter.open_source_license}}' != 'GPLv3':
|
if '{{ cookiecutter.open_source_license}}' != 'GPLv3':
|
||||||
remove_gplv3_files()
|
remove_gplv3_files()
|
||||||
|
|
||||||
if '{{ cookiecutter.use_pycharm }}'.lower() == 'n':
|
if '{{ cookiecutter.use_pycharm }}'.lower() == 'n':
|
||||||
|
@ -250,7 +241,11 @@ def main():
|
||||||
if '{{ cookiecutter.use_docker }}'.lower() == 'n':
|
if '{{ cookiecutter.use_docker }}'.lower() == 'n':
|
||||||
remove_docker_files()
|
remove_docker_files()
|
||||||
|
|
||||||
remove_paas_files()
|
if '{{ cookiecutter.use_heroku }}'.lower() == 'n':
|
||||||
|
remove_heroku_files()
|
||||||
|
|
||||||
|
if '{{ cookiecutter.use_docker }}'.lower() == 'n' and '{{ cookiecutter.use_heroku }}'.lower() == 'n':
|
||||||
|
remove_dotenv_file()
|
||||||
|
|
||||||
if '{{ cookiecutter.js_task_runner}}'.lower() == 'gulp':
|
if '{{ cookiecutter.js_task_runner}}'.lower() == 'gulp':
|
||||||
remove_grunt_files()
|
remove_grunt_files()
|
||||||
|
@ -278,6 +273,9 @@ def main():
|
||||||
if '{{ cookiecutter.use_celery }}'.lower() == 'n':
|
if '{{ cookiecutter.use_celery }}'.lower() == 'n':
|
||||||
remove_celery_app()
|
remove_celery_app()
|
||||||
|
|
||||||
|
if '{{ cookiecutter.use_travisci }}'.lower() == 'n':
|
||||||
|
remove_dottravisyml_file()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -11,6 +11,9 @@ project_slug = '{{ cookiecutter.project_slug }}'
|
||||||
if hasattr(project_slug, 'isidentifier'):
|
if hasattr(project_slug, 'isidentifier'):
|
||||||
assert project_slug.isidentifier(), "'{}' project slug is not a valid Python identifier.".format(project_slug)
|
assert project_slug.isidentifier(), "'{}' project slug is not a valid Python identifier.".format(project_slug)
|
||||||
|
|
||||||
|
assert "\\" not in "{{ cookiecutter.author_name }}", "Don't include backslashes in author name."
|
||||||
|
|
||||||
|
|
||||||
using_docker = '{{ cookiecutter.use_docker }}'.lower()
|
using_docker = '{{ cookiecutter.use_docker }}'.lower()
|
||||||
if using_docker == 'n':
|
if using_docker == 'n':
|
||||||
TERMINATOR = "\x1b[0m"
|
TERMINATOR = "\x1b[0m"
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
cookiecutter==1.6.0
|
cookiecutter==1.6.0
|
||||||
flake8==3.5.0 # pyup: != 2.6.0
|
|
||||||
sh==1.12.14
|
sh==1.12.14
|
||||||
binaryornot==0.4.4
|
binaryornot==0.4.4
|
||||||
|
|
||||||
# Testing
|
|
||||||
pytest==3.3.2
|
# Code quality
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
flake8==3.5.0
|
||||||
pycodestyle==2.3.1
|
pycodestyle==2.3.1
|
||||||
pyflakes==1.6.0
|
pyflakes==1.6.0
|
||||||
|
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
tox==2.9.1
|
tox==2.9.1
|
||||||
|
pytest==3.4.2
|
||||||
pytest-cookies==0.3.0
|
pytest-cookies==0.3.0
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
# These requirements prevented an upgrade to Django 1.11.
|
|
||||||
django-autoslug==1.9.3
|
|
5
setup.py
5
setup.py
|
@ -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 = '1.11.9'
|
version = '2.0.2'
|
||||||
|
|
||||||
if sys.argv[-1] == 'tag':
|
if sys.argv[-1] == 'tag':
|
||||||
os.system('git tag -a %s -m "version %s"' % (version, version))
|
os.system('git tag -a %s -m "version %s"' % (version, version))
|
||||||
|
@ -34,7 +34,7 @@ setup(
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 4 - Beta',
|
'Development Status :: 4 - Beta',
|
||||||
'Environment :: Console',
|
'Environment :: Console',
|
||||||
'Framework :: Django :: 1.11',
|
'Framework :: Django :: 2.0',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'Natural Language :: English',
|
'Natural Language :: English',
|
||||||
'License :: OSI Approved :: BSD License',
|
'License :: OSI Approved :: BSD License',
|
||||||
|
@ -42,7 +42,6 @@ setup(
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3.6',
|
'Programming Language :: Python :: 3.6',
|
||||||
'Programming Language :: Python :: Implementation :: CPython',
|
'Programming Language :: Python :: Implementation :: CPython',
|
||||||
'Programming Language :: Python :: Implementation :: PyPy',
|
|
||||||
'Topic :: Software Development',
|
'Topic :: Software Development',
|
||||||
],
|
],
|
||||||
keywords=(
|
keywords=(
|
||||||
|
|
|
@ -12,10 +12,13 @@ cd .cache/docker
|
||||||
|
|
||||||
# create the project using the default settings in cookiecutter.json
|
# create the project using the default settings in cookiecutter.json
|
||||||
cookiecutter ../../ --no-input --overwrite-if-exists use_docker=y js_task_runner=None
|
cookiecutter ../../ --no-input --overwrite-if-exists use_docker=y js_task_runner=None
|
||||||
cd project_name
|
cd my_awesome_project
|
||||||
|
|
||||||
# run the project's tests
|
# run the project's tests
|
||||||
docker-compose -f local.yml run django python manage.py test
|
docker-compose -f local.yml run django python manage.py test
|
||||||
|
|
||||||
# return non-zero status code if there are migrations that have not been created
|
# return non-zero status code if there are migrations that have not been created
|
||||||
docker-compose -f local.yml run django python manage.py makemigrations --dry-run --check || { echo "ERROR: there were changes in the models, but migration listed above have not been created and are not saved in version control"; exit 1; }
|
docker-compose -f local.yml run django python manage.py makemigrations --dry-run --check || { echo "ERROR: there were changes in the models, but migration listed above have not been created and are not saved in version control"; exit 1; }
|
||||||
|
|
||||||
|
# Test support for translations
|
||||||
|
docker-compose -f local.yml run django python manage.py makemessages
|
||||||
|
|
9
tox.ini
9
tox.ini
|
@ -3,10 +3,5 @@ skipsdist = true
|
||||||
envlist = py36
|
envlist = py36
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
passenv = LC_ALL, LANG, HOME
|
deps = -rrequirements.txt
|
||||||
deps =
|
commands = pytest {posargs:./tests}
|
||||||
binaryornot
|
|
||||||
flake8==2.5.5
|
|
||||||
pytest-cookies
|
|
||||||
sh
|
|
||||||
commands = py.test {posargs:tests}
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ module.exports = function (grunt) {
|
||||||
|
|
||||||
processors: [
|
processors: [
|
||||||
require('pixrem')(), // add fallbacks for rem units
|
require('pixrem')(), // add fallbacks for rem units
|
||||||
require('autoprefixer-core')({browsers: [
|
require('autoprefixer')({browsers: [
|
||||||
'Android 2.3',
|
'Android 2.3',
|
||||||
'Android >= 4',
|
'Android >= 4',
|
||||||
'Chrome >= 20',
|
'Chrome >= 20',
|
||||||
|
|
|
@ -1,7 +1,18 @@
|
||||||
FROM python:3.6
|
FROM python:3.6-alpine
|
||||||
|
|
||||||
ENV PYTHONUNBUFFERED 1
|
ENV PYTHONUNBUFFERED 1
|
||||||
|
|
||||||
|
RUN apk update \
|
||||||
|
# psycopg2 dependencies
|
||||||
|
&& apk add --virtual build-deps gcc python3-dev musl-dev \
|
||||||
|
&& apk add postgresql-dev \
|
||||||
|
# Pillow dependencies
|
||||||
|
&& apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev \
|
||||||
|
# CFFI dependencies
|
||||||
|
&& apk add libffi-dev openssl-dev py-cffi \
|
||||||
|
# Translations dependencies
|
||||||
|
&& apk add gettext
|
||||||
|
|
||||||
# Requirements have to be pulled and installed here, otherwise caching won't work
|
# Requirements have to be pulled and installed here, otherwise caching won't work
|
||||||
COPY ./requirements /requirements
|
COPY ./requirements /requirements
|
||||||
RUN pip install -r /requirements/local.txt
|
RUN pip install -r /requirements/local.txt
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/sh
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/sh
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/sh
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
FROM python:3.6
|
FROM python:3.6-alpine
|
||||||
|
|
||||||
ENV PYTHONUNBUFFERED 1
|
ENV PYTHONUNBUFFERED 1
|
||||||
|
|
||||||
RUN groupadd -r django \
|
RUN apk update \
|
||||||
&& useradd -r -g django django
|
# psycopg2 dependencies
|
||||||
|
&& apk add --virtual build-deps gcc python3-dev musl-dev \
|
||||||
|
&& apk add postgresql-dev \
|
||||||
|
# Pillow dependencies
|
||||||
|
&& apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev \
|
||||||
|
# CFFI dependencies
|
||||||
|
&& apk add libffi-dev openssl-dev py-cffi
|
||||||
|
|
||||||
|
RUN addgroup -S django \
|
||||||
|
&& adduser -S -G django django
|
||||||
|
|
||||||
# Requirements have to be pulled and installed here, otherwise caching won't work
|
# Requirements have to be pulled and installed here, otherwise caching won't work
|
||||||
COPY ./requirements /requirements
|
COPY ./requirements /requirements
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/sh
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/sh
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/sh
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
@ -25,7 +25,7 @@ export DATABASE_URL=postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres:5432/$
|
||||||
export CELERY_BROKER_URL=$REDIS_URL/0
|
export CELERY_BROKER_URL=$REDIS_URL/0
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
function postgres_ready(){
|
postgres_ready() {
|
||||||
python << END
|
python << END
|
||||||
import sys
|
import sys
|
||||||
import psycopg2
|
import psycopg2
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env bash
|
#!/bin/sh
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
@ -6,4 +6,4 @@ set -o nounset
|
||||||
|
|
||||||
|
|
||||||
python /app/manage.py collectstatic --noinput
|
python /app/manage.py collectstatic --noinput
|
||||||
/usr/local/bin/gunicorn config.wsgi -w 4 -b 0.0.0.0:5000 --chdir=/app
|
/usr/local/bin/gunicorn config.wsgi -b 0.0.0.0:5000 --chdir=/app
|
||||||
|
|
|
@ -1,232 +1,119 @@
|
||||||
"""
|
"""
|
||||||
Base settings for {{cookiecutter.project_name}} project.
|
Base settings to build other settings files upon.
|
||||||
|
|
||||||
For more information on this file, see
|
|
||||||
https://docs.djangoproject.com/en/dev/topics/settings/
|
|
||||||
|
|
||||||
For the full list of settings and their values, see
|
|
||||||
https://docs.djangoproject.com/en/dev/ref/settings/
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import environ
|
import environ
|
||||||
|
|
||||||
ROOT_DIR = environ.Path(__file__) - 3 # ({{ cookiecutter.project_slug }}/config/settings/base.py - 3 = {{ cookiecutter.project_slug }}/)
|
ROOT_DIR = environ.Path(__file__) - 3 # ({{ cookiecutter.project_slug }}/config/settings/base.py - 3 = {{ cookiecutter.project_slug }}/)
|
||||||
APPS_DIR = ROOT_DIR.path('{{ cookiecutter.project_slug }}')
|
APPS_DIR = ROOT_DIR.path('{{ cookiecutter.project_slug }}')
|
||||||
|
|
||||||
# Load operating system environment variables and then prepare to use them
|
|
||||||
env = environ.Env()
|
env = environ.Env()
|
||||||
|
|
||||||
# .env file, should load only in development environment
|
|
||||||
READ_DOT_ENV_FILE = env.bool('DJANGO_READ_DOT_ENV_FILE', default=False)
|
READ_DOT_ENV_FILE = env.bool('DJANGO_READ_DOT_ENV_FILE', default=False)
|
||||||
|
|
||||||
if READ_DOT_ENV_FILE:
|
if READ_DOT_ENV_FILE:
|
||||||
# Operating System Environment variables have precedence over variables defined in the .env file,
|
# OS environment variables take precedence over variables from .env
|
||||||
# that is to say variables from the .env files will only be used if not defined
|
env.read_env(str(ROOT_DIR.path('.env')))
|
||||||
# as environment variables.
|
|
||||||
env_file = str(ROOT_DIR.path('.env'))
|
|
||||||
print('Loading : {}'.format(env_file))
|
|
||||||
env.read_env(env_file)
|
|
||||||
print('The .env file has been loaded. See base.py for more information')
|
|
||||||
|
|
||||||
# APP CONFIGURATION
|
# GENERAL
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
|
||||||
|
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
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
|
||||||
|
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
|
||||||
|
|
||||||
|
# DATABASES
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#databases
|
||||||
|
{% if cookiecutter.use_docker == 'y' -%}
|
||||||
|
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
|
||||||
|
|
||||||
|
# URLS
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf
|
||||||
|
ROOT_URLCONF = 'config.urls'
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
|
||||||
|
WSGI_APPLICATION = 'config.wsgi.application'
|
||||||
|
|
||||||
|
# APPS
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
DJANGO_APPS = [
|
DJANGO_APPS = [
|
||||||
# Default Django apps:
|
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.sites',
|
'django.contrib.sites',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
# 'django.contrib.humanize', # Handy template tags
|
||||||
# Useful template tags:
|
|
||||||
# 'django.contrib.humanize',
|
|
||||||
|
|
||||||
# Admin
|
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
]
|
]
|
||||||
THIRD_PARTY_APPS = [
|
THIRD_PARTY_APPS = [
|
||||||
'crispy_forms', # Form layouts
|
'crispy_forms',
|
||||||
'allauth', # registration
|
|
||||||
'allauth.account', # registration
|
|
||||||
'allauth.socialaccount', # registration
|
|
||||||
]
|
|
||||||
|
|
||||||
# Apps specific for this project go here.
|
'allauth',
|
||||||
|
'allauth.account',
|
||||||
|
'allauth.socialaccount',
|
||||||
|
]
|
||||||
LOCAL_APPS = [
|
LOCAL_APPS = [
|
||||||
# custom users app
|
|
||||||
'{{ 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
|
||||||
# See: 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
|
||||||
|
|
||||||
# MIDDLEWARE CONFIGURATION
|
# MIGRATIONS
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
MIDDLEWARE = [
|
|
||||||
'django.middleware.security.SecurityMiddleware',
|
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
|
||||||
'django.middleware.common.CommonMiddleware',
|
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
||||||
]
|
|
||||||
|
|
||||||
# MIGRATIONS CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#migration-modules
|
||||||
MIGRATION_MODULES = {
|
MIGRATION_MODULES = {
|
||||||
'sites': '{{ cookiecutter.project_slug }}.contrib.sites.migrations'
|
'sites': '{{ cookiecutter.project_slug }}.contrib.sites.migrations'
|
||||||
}
|
}
|
||||||
|
|
||||||
# DEBUG
|
# AUTHENTICATION
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug
|
# https://docs.djangoproject.com/en/dev/ref/settings/#authentication-backends
|
||||||
DEBUG = env.bool('DJANGO_DEBUG', False)
|
AUTHENTICATION_BACKENDS = [
|
||||||
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
# FIXTURE CONFIGURATION
|
'allauth.account.auth_backends.AuthenticationBackend',
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FIXTURE_DIRS
|
|
||||||
FIXTURE_DIRS = (
|
|
||||||
str(APPS_DIR.path('fixtures')),
|
|
||||||
)
|
|
||||||
|
|
||||||
# EMAIL CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND', default='django.core.mail.backends.smtp.EmailBackend')
|
|
||||||
|
|
||||||
# MANAGER CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#admins
|
|
||||||
ADMINS = [
|
|
||||||
("""{{cookiecutter.author_name}}""", '{{cookiecutter.email}}'),
|
|
||||||
]
|
]
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model
|
||||||
|
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'
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#managers
|
# PASSWORDS
|
||||||
MANAGERS = ADMINS
|
|
||||||
|
|
||||||
# DATABASE CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases
|
# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers
|
||||||
# Uses django-environ to accept uri format
|
|
||||||
# See: https://django-environ.readthedocs.io/en/latest/#supported-types
|
|
||||||
DATABASES = {
|
|
||||||
'default': env.db('DATABASE_URL', default='postgres://{% if cookiecutter.windows == 'y' %}localhost{% endif %}/{{cookiecutter.project_slug}}'),
|
|
||||||
}
|
|
||||||
DATABASES['default']['ATOMIC_REQUESTS'] = True
|
|
||||||
|
|
||||||
|
|
||||||
# GENERAL CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Local time zone for this installation. Choices can be found here:
|
|
||||||
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
|
|
||||||
# although not all choices may be available on all operating systems.
|
|
||||||
# In a Windows environment this must be set to your system time zone.
|
|
||||||
TIME_ZONE = '{{ cookiecutter.timezone }}'
|
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#language-code
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#site-id
|
|
||||||
SITE_ID = 1
|
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
|
|
||||||
USE_I18N = True
|
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n
|
|
||||||
USE_L10N = True
|
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz
|
|
||||||
USE_TZ = True
|
|
||||||
|
|
||||||
# TEMPLATE CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#templates
|
|
||||||
TEMPLATES = [
|
|
||||||
{
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND
|
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
|
|
||||||
'DIRS': [
|
|
||||||
str(APPS_DIR.path('templates')),
|
|
||||||
],
|
|
||||||
'OPTIONS': {
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug
|
|
||||||
'debug': DEBUG,
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
|
|
||||||
# https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
|
|
||||||
'loaders': [
|
|
||||||
'django.template.loaders.filesystem.Loader',
|
|
||||||
'django.template.loaders.app_directories.Loader',
|
|
||||||
],
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
|
|
||||||
'context_processors': [
|
|
||||||
'django.template.context_processors.debug',
|
|
||||||
'django.template.context_processors.request',
|
|
||||||
'django.contrib.auth.context_processors.auth',
|
|
||||||
'django.template.context_processors.i18n',
|
|
||||||
'django.template.context_processors.media',
|
|
||||||
'django.template.context_processors.static',
|
|
||||||
'django.template.context_processors.tz',
|
|
||||||
'django.contrib.messages.context_processors.messages',
|
|
||||||
# Your stuff: custom template context processors go here
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
# See: http://django-crispy-forms.readthedocs.io/en/latest/install.html#template-packs
|
|
||||||
CRISPY_TEMPLATE_PACK = 'bootstrap4'
|
|
||||||
|
|
||||||
# STATIC FILE CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root
|
|
||||||
STATIC_ROOT = str(ROOT_DIR('staticfiles'))
|
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
|
|
||||||
STATIC_URL = '/static/'
|
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
|
|
||||||
STATICFILES_DIRS = [
|
|
||||||
str(APPS_DIR.path('static')),
|
|
||||||
]
|
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
|
|
||||||
STATICFILES_FINDERS = [
|
|
||||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
|
||||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
|
||||||
]
|
|
||||||
|
|
||||||
# MEDIA CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root
|
|
||||||
MEDIA_ROOT = str(APPS_DIR('media'))
|
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url
|
|
||||||
MEDIA_URL = '/media/'
|
|
||||||
|
|
||||||
# URL Configuration
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
ROOT_URLCONF = 'config.urls'
|
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
|
|
||||||
WSGI_APPLICATION = 'config.wsgi.application'
|
|
||||||
|
|
||||||
# PASSWORD STORAGE SETTINGS
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# See https://docs.djangoproject.com/en/dev/topics/auth/passwords/#using-argon2-with-django
|
|
||||||
PASSWORD_HASHERS = [
|
PASSWORD_HASHERS = [
|
||||||
|
# https://docs.djangoproject.com/en/dev/topics/auth/passwords/#using-argon2-with-django
|
||||||
'django.contrib.auth.hashers.Argon2PasswordHasher',
|
'django.contrib.auth.hashers.Argon2PasswordHasher',
|
||||||
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
|
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
|
||||||
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
|
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
|
||||||
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
|
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
|
||||||
'django.contrib.auth.hashers.BCryptPasswordHasher',
|
'django.contrib.auth.hashers.BCryptPasswordHasher',
|
||||||
]
|
]
|
||||||
|
|
||||||
# PASSWORD VALIDATION
|
|
||||||
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators
|
# 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',
|
||||||
|
@ -242,50 +129,142 @@ AUTH_PASSWORD_VALIDATORS = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
# AUTHENTICATION CONFIGURATION
|
# MIDDLEWARE
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
AUTHENTICATION_BACKENDS = [
|
# https://docs.djangoproject.com/en/dev/ref/settings/#middleware
|
||||||
'django.contrib.auth.backends.ModelBackend',
|
MIDDLEWARE = [
|
||||||
'allauth.account.auth_backends.AuthenticationBackend',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
]
|
]
|
||||||
|
|
||||||
# Some really nice defaults
|
# STATIC
|
||||||
ACCOUNT_AUTHENTICATION_METHOD = 'username'
|
# ------------------------------------------------------------------------------
|
||||||
ACCOUNT_EMAIL_REQUIRED = True
|
# https://docs.djangoproject.com/en/dev/ref/settings/#static-root
|
||||||
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
|
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')),
|
||||||
|
]
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
|
||||||
|
STATICFILES_FINDERS = [
|
||||||
|
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||||
|
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||||
|
]
|
||||||
|
|
||||||
ACCOUNT_ALLOW_REGISTRATION = env.bool('DJANGO_ACCOUNT_ALLOW_REGISTRATION', True)
|
# MEDIA
|
||||||
ACCOUNT_ADAPTER = '{{cookiecutter.project_slug}}.users.adapters.AccountAdapter'
|
# ------------------------------------------------------------------------------
|
||||||
SOCIALACCOUNT_ADAPTER = '{{cookiecutter.project_slug}}.users.adapters.SocialAccountAdapter'
|
# https://docs.djangoproject.com/en/dev/ref/settings/#media-root
|
||||||
|
MEDIA_ROOT = str(APPS_DIR('media'))
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#media-url
|
||||||
|
MEDIA_URL = '/media/'
|
||||||
|
|
||||||
# Custom user app defaults
|
# TEMPLATES
|
||||||
# Select the correct user model
|
# ------------------------------------------------------------------------------
|
||||||
AUTH_USER_MODEL = 'users.User'
|
# https://docs.djangoproject.com/en/dev/ref/settings/#templates
|
||||||
LOGIN_REDIRECT_URL = 'users:redirect'
|
TEMPLATES = [
|
||||||
LOGIN_URL = 'account_login'
|
{
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
|
||||||
|
'DIRS': [
|
||||||
|
str(APPS_DIR.path('templates')),
|
||||||
|
],
|
||||||
|
'OPTIONS': {
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#template-debug
|
||||||
|
'debug': DEBUG,
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
|
||||||
|
'loaders': [
|
||||||
|
'django.template.loaders.filesystem.Loader',
|
||||||
|
'django.template.loaders.app_directories.Loader',
|
||||||
|
],
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.template.context_processors.i18n',
|
||||||
|
'django.template.context_processors.media',
|
||||||
|
'django.template.context_processors.static',
|
||||||
|
'django.template.context_processors.tz',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
# http://django-crispy-forms.readthedocs.io/en/latest/install.html#template-packs
|
||||||
|
CRISPY_TEMPLATE_PACK = 'bootstrap4'
|
||||||
|
|
||||||
# SLUGLIFIER
|
# FIXTURES
|
||||||
AUTOSLUG_SLUGIFY_FUNCTION = 'slugify.slugify'
|
# ------------------------------------------------------------------------------
|
||||||
{% if cookiecutter.use_celery == 'y' %}
|
# https://docs.djangoproject.com/en/dev/ref/settings/#fixture-dirs
|
||||||
########## CELERY
|
FIXTURE_DIRS = (
|
||||||
|
str(APPS_DIR.path('fixtures')),
|
||||||
|
)
|
||||||
|
|
||||||
|
# EMAIL
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
|
||||||
|
EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND', default='django.core.mail.backends.smtp.EmailBackend')
|
||||||
|
|
||||||
|
# ADMIN
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Django Admin URL regex.
|
||||||
|
ADMIN_URL = r'^admin/'
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#admins
|
||||||
|
ADMINS = [
|
||||||
|
("""{{cookiecutter.author_name}}""", '{{cookiecutter.email}}'),
|
||||||
|
]
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#managers
|
||||||
|
MANAGERS = ADMINS
|
||||||
|
|
||||||
|
{% if cookiecutter.use_celery == 'y' -%}
|
||||||
|
# Celery
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
INSTALLED_APPS += ['{{cookiecutter.project_slug}}.taskapp.celery.CeleryConfig']
|
INSTALLED_APPS += ['{{cookiecutter.project_slug}}.taskapp.celery.CeleryConfig']
|
||||||
|
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-broker_url
|
||||||
CELERY_BROKER_URL = env('CELERY_BROKER_URL', default='django://')
|
CELERY_BROKER_URL = env('CELERY_BROKER_URL', default='django://')
|
||||||
|
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-result_backend
|
||||||
if CELERY_BROKER_URL == 'django://':
|
if CELERY_BROKER_URL == 'django://':
|
||||||
CELERY_RESULT_BACKEND = 'redis://'
|
CELERY_RESULT_BACKEND = 'redis://'
|
||||||
else:
|
else:
|
||||||
CELERY_RESULT_BACKEND = CELERY_BROKER_URL
|
CELERY_RESULT_BACKEND = CELERY_BROKER_URL
|
||||||
########## END CELERY
|
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-accept_content
|
||||||
{% endif %}
|
CELERY_ACCEPT_CONTENT = ['json']
|
||||||
|
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-task_serializer
|
||||||
|
CELERY_TASK_SERIALIZER = 'json'
|
||||||
|
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-result_serializer
|
||||||
|
CELERY_RESULT_SERIALIZER = 'json'
|
||||||
|
|
||||||
{%- if cookiecutter.use_compressor == 'y'-%}
|
{%- endif %}
|
||||||
|
# django-allauth
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
ACCOUNT_ALLOW_REGISTRATION = env.bool('DJANGO_ACCOUNT_ALLOW_REGISTRATION', True)
|
||||||
|
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||||
|
ACCOUNT_AUTHENTICATION_METHOD = 'username'
|
||||||
|
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||||
|
ACCOUNT_EMAIL_REQUIRED = True
|
||||||
|
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||||
|
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
|
||||||
|
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||||
|
ACCOUNT_ADAPTER = '{{cookiecutter.project_slug}}.users.adapters.AccountAdapter'
|
||||||
|
# https://django-allauth.readthedocs.io/en/latest/configuration.html
|
||||||
|
SOCIALACCOUNT_ADAPTER = '{{cookiecutter.project_slug}}.users.adapters.SocialAccountAdapter'
|
||||||
|
|
||||||
|
{% if cookiecutter.use_compressor == 'y' -%}
|
||||||
# django-compressor
|
# django-compressor
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
# https://django-compressor.readthedocs.io/en/latest/quickstart/#installation
|
||||||
INSTALLED_APPS += ['compressor']
|
INSTALLED_APPS += ['compressor']
|
||||||
STATICFILES_FINDERS += ['compressor.finders.CompressorFinder']
|
STATICFILES_FINDERS += ['compressor.finders.CompressorFinder']
|
||||||
|
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
# Your stuff...
|
||||||
# Location of root django.contrib.admin URL, use {% raw %}{% url 'admin:index' %}{% endraw %}
|
|
||||||
ADMIN_URL = r'^admin/'
|
|
||||||
|
|
||||||
# Your common stuff: Below this line define 3rd party library settings
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,47 +1,21 @@
|
||||||
"""
|
|
||||||
Local settings for {{cookiecutter.project_name}} project.
|
|
||||||
|
|
||||||
- Run in Debug mode
|
|
||||||
{% if cookiecutter.use_mailhog == 'y' and cookiecutter.use_docker == 'y' %}
|
|
||||||
- Use mailhog for emails via Docker
|
|
||||||
{% elif cookiecutter.use_mailhog == 'y' and cookiecutter.use_docker == 'n' %}
|
|
||||||
- Use mailhog for emails
|
|
||||||
{% else %}
|
|
||||||
- Use console backend for emails
|
|
||||||
{% endif %}
|
|
||||||
- Add Django Debug Toolbar
|
|
||||||
- Add django-extensions as app
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .base import * # noqa
|
from .base import * # noqa
|
||||||
|
from .base import env
|
||||||
|
|
||||||
# DEBUG
|
# GENERAL
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
|
||||||
DEBUG = env.bool('DJANGO_DEBUG', default=True)
|
DEBUG = env.bool('DJANGO_DEBUG', default=True)
|
||||||
TEMPLATES[0]['OPTIONS']['debug'] = DEBUG
|
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
||||||
|
|
||||||
# SECRET CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
|
||||||
# Note: This key only used for development and testing.
|
|
||||||
SECRET_KEY = env('DJANGO_SECRET_KEY', default='!!!SET DJANGO_SECRET_KEY!!!')
|
SECRET_KEY = env('DJANGO_SECRET_KEY', default='!!!SET DJANGO_SECRET_KEY!!!')
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
||||||
|
ALLOWED_HOSTS = [
|
||||||
|
"localhost",
|
||||||
|
"0.0.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
# Mail settings
|
# CACHES
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
EMAIL_PORT = 1025
|
|
||||||
{% if cookiecutter.use_mailhog == 'y' and cookiecutter.use_docker == 'y' %}
|
|
||||||
EMAIL_HOST = env('EMAIL_HOST', default='mailhog')
|
|
||||||
{% elif cookiecutter.use_mailhog == 'y' and cookiecutter.use_docker == 'n' %}
|
|
||||||
EMAIL_HOST = 'localhost'
|
|
||||||
{% else %}
|
|
||||||
EMAIL_HOST = 'localhost'
|
|
||||||
EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND',
|
|
||||||
default='django.core.mail.backends.console.EmailBackend')
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
# CACHING
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#caches
|
||||||
CACHES = {
|
CACHES = {
|
||||||
'default': {
|
'default': {
|
||||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||||
|
@ -49,40 +23,62 @@ CACHES = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# TEMPLATES
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#templates
|
||||||
|
TEMPLATES[0]['OPTIONS']['debug'] = DEBUG # noqa F405
|
||||||
|
|
||||||
|
# EMAIL
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
{% if cookiecutter.use_mailhog == 'y' and cookiecutter.use_docker == 'y' -%}
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#email-host
|
||||||
|
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 -%}
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
|
||||||
|
EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND', default='django.core.mail.backends.console.EmailBackend')
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#email-host
|
||||||
|
EMAIL_HOST = 'localhost'
|
||||||
|
{%- endif %}
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#email-port
|
||||||
|
EMAIL_PORT = 1025
|
||||||
|
|
||||||
# django-debug-toolbar
|
# django-debug-toolbar
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware', ]
|
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#prerequisites
|
||||||
INSTALLED_APPS += ['debug_toolbar', ]
|
INSTALLED_APPS += ['debug_toolbar'] # noqa F405
|
||||||
|
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#middleware
|
||||||
INTERNAL_IPS = ['127.0.0.1', '10.0.2.2', ]
|
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware'] # noqa F405
|
||||||
{% if cookiecutter.use_docker == 'y' %}
|
# https://django-debug-toolbar.readthedocs.io/en/latest/configuration.html#debug-toolbar-config
|
||||||
{# [cookiecutter-django] This is a workaround to flake8 "imported but unused" errors #}
|
|
||||||
import socket
|
|
||||||
import os
|
|
||||||
# tricks to have debug toolbar when developing with docker
|
|
||||||
if os.environ.get('USE_DOCKER') == 'yes':
|
|
||||||
hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
|
|
||||||
INTERNAL_IPS += [ip[:-1] + '1' for ip in ips]
|
|
||||||
{% endif %}
|
|
||||||
DEBUG_TOOLBAR_CONFIG = {
|
DEBUG_TOOLBAR_CONFIG = {
|
||||||
'DISABLE_PANELS': [
|
'DISABLE_PANELS': [
|
||||||
'debug_toolbar.panels.redirects.RedirectsPanel',
|
'debug_toolbar.panels.redirects.RedirectsPanel',
|
||||||
],
|
],
|
||||||
'SHOW_TEMPLATE_CONTEXT': True,
|
'SHOW_TEMPLATE_CONTEXT': True,
|
||||||
}
|
}
|
||||||
|
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#internal-ips
|
||||||
|
INTERNAL_IPS = ['127.0.0.1', '10.0.2.2']
|
||||||
|
{% if cookiecutter.use_docker == 'y' -%}
|
||||||
|
import socket
|
||||||
|
import os
|
||||||
|
if os.environ.get('USE_DOCKER') == 'yes':
|
||||||
|
hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
|
||||||
|
INTERNAL_IPS += [ip[:-1] + '1' for ip in ips]
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
# django-extensions
|
# django-extensions
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
INSTALLED_APPS += ['django_extensions', ]
|
# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration
|
||||||
|
INSTALLED_APPS += ['django_extensions'] # noqa F405
|
||||||
|
{% if cookiecutter.use_celery == 'y' -%}
|
||||||
|
|
||||||
# TESTING
|
# Celery
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
TEST_RUNNER = 'django.test.runner.DiscoverRunner'
|
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-task_always_eager
|
||||||
{% if cookiecutter.use_celery == 'y' %}
|
|
||||||
########## CELERY
|
|
||||||
# In development, all tasks will be executed locally by blocking until the task returns
|
|
||||||
CELERY_ALWAYS_EAGER = True
|
CELERY_ALWAYS_EAGER = True
|
||||||
########## END CELERY
|
|
||||||
{% endif %}
|
{%- endif %}
|
||||||
# Your local stuff: Below this line define 3rd party library settings
|
# Your stuff...
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,203 +1,190 @@
|
||||||
"""
|
|
||||||
Production settings for {{cookiecutter.project_name}} project.
|
|
||||||
|
|
||||||
{% if cookiecutter.use_whitenoise == 'y' -%}
|
|
||||||
- Use WhiteNoise for serving static files{% endif %}
|
|
||||||
- Use Amazon's S3 for storing {% if cookiecutter.use_whitenoise == 'n' -%}static files and {% endif %}uploaded media
|
|
||||||
- Use mailgun to send emails
|
|
||||||
- Use Redis for cache
|
|
||||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
|
||||||
- Use sentry for error logging
|
|
||||||
{% endif %}
|
|
||||||
{% if cookiecutter.use_opbeat == 'y' %}
|
|
||||||
- Use opbeat for error reporting
|
|
||||||
{% endif %}
|
|
||||||
"""
|
|
||||||
|
|
||||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
|
||||||
import logging
|
import logging
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
from .base import * # noqa
|
from .base import * # noqa
|
||||||
|
from .base import env
|
||||||
|
|
||||||
# SECRET CONFIGURATION
|
# GENERAL
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
||||||
# Raises ImproperlyConfigured exception if DJANGO_SECRET_KEY not in os.environ
|
|
||||||
SECRET_KEY = env('DJANGO_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
|
||||||
# This ensures that Django will be able to detect a secure connection
|
|
||||||
# properly on Heroku.
|
|
||||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
|
||||||
|
|
||||||
{%- if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
|
||||||
# raven sentry client
|
|
||||||
# See https://docs.sentry.io/clients/python/integrations/django/
|
|
||||||
INSTALLED_APPS += ['raven.contrib.django.raven_compat', ]
|
|
||||||
{% endif %}
|
|
||||||
{%- if cookiecutter.use_whitenoise == 'y' %}
|
|
||||||
# Use Whitenoise to serve static files
|
|
||||||
# See: https://whitenoise.readthedocs.io/
|
|
||||||
WHITENOISE_MIDDLEWARE = ['whitenoise.middleware.WhiteNoiseMiddleware', ]
|
|
||||||
MIDDLEWARE = WHITENOISE_MIDDLEWARE + MIDDLEWARE
|
|
||||||
{% endif %}
|
|
||||||
{%- if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
|
||||||
RAVEN_MIDDLEWARE = ['raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware']
|
|
||||||
MIDDLEWARE = RAVEN_MIDDLEWARE + MIDDLEWARE
|
|
||||||
{% endif %}
|
|
||||||
{%- if cookiecutter.use_opbeat == 'y' -%}
|
|
||||||
# opbeat integration
|
|
||||||
# See https://opbeat.com/languages/django/
|
|
||||||
INSTALLED_APPS += ['opbeat.contrib.django', ]
|
|
||||||
OPBEAT = {
|
|
||||||
'ORGANIZATION_ID': env('DJANGO_OPBEAT_ORGANIZATION_ID'),
|
|
||||||
'APP_ID': env('DJANGO_OPBEAT_APP_ID'),
|
|
||||||
'SECRET_TOKEN': env('DJANGO_OPBEAT_SECRET_TOKEN')
|
|
||||||
}
|
|
||||||
MIDDLEWARE = ['opbeat.contrib.django.middleware.OpbeatAPMMiddleware', ] + MIDDLEWARE
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
# SECURITY CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# See https://docs.djangoproject.com/en/dev/ref/middleware/#module-django.middleware.security
|
DATABASES['default'] = env.db('DATABASE_URL') # noqa F405
|
||||||
# and https://docs.djangoproject.com/en/dev/howto/deployment/checklist/#run-manage-py-check-deploy
|
DATABASES['default']['ATOMIC_REQUESTS'] = True # noqa F405
|
||||||
|
DATABASES['default']['CONN_MAX_AGE'] = env.int('CONN_MAX_AGE', default=60) # noqa F405
|
||||||
|
|
||||||
# set this to 60 seconds and then to 518400 when you can prove it works
|
# CACHES
|
||||||
SECURE_HSTS_SECONDS = 60
|
|
||||||
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool(
|
|
||||||
'DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS', default=True)
|
|
||||||
SECURE_CONTENT_TYPE_NOSNIFF = env.bool(
|
|
||||||
'DJANGO_SECURE_CONTENT_TYPE_NOSNIFF', default=True)
|
|
||||||
SECURE_BROWSER_XSS_FILTER = True
|
|
||||||
SESSION_COOKIE_SECURE = True
|
|
||||||
SESSION_COOKIE_HTTPONLY = True
|
|
||||||
SECURE_SSL_REDIRECT = env.bool('DJANGO_SECURE_SSL_REDIRECT', default=True)
|
|
||||||
CSRF_COOKIE_SECURE = True
|
|
||||||
CSRF_COOKIE_HTTPONLY = True
|
|
||||||
X_FRAME_OPTIONS = 'DENY'
|
|
||||||
|
|
||||||
# SITE CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Hosts/domain names that are valid for this site
|
|
||||||
# See https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
|
||||||
ALLOWED_HOSTS = env.list('DJANGO_ALLOWED_HOSTS', default=['{{cookiecutter.domain_name}}', ])
|
|
||||||
# END SITE CONFIGURATION
|
|
||||||
|
|
||||||
INSTALLED_APPS += ['gunicorn', ]
|
|
||||||
|
|
||||||
|
|
||||||
# STORAGE CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Uploaded Media Files
|
|
||||||
# ------------------------
|
|
||||||
# See: http://django-storages.readthedocs.io/en/latest/index.html
|
|
||||||
INSTALLED_APPS += ['storages', ]
|
|
||||||
|
|
||||||
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_AUTO_CREATE_BUCKET = True
|
|
||||||
AWS_QUERYSTRING_AUTH = False
|
|
||||||
|
|
||||||
# AWS cache settings, don't change unless you know what you're doing:
|
|
||||||
AWS_EXPIRY = 60 * 60 * 24 * 7
|
|
||||||
|
|
||||||
# TODO See: https://github.com/jschneier/django-storages/issues/47
|
|
||||||
# Revert the following and use str after the above-mentioned bug is fixed in
|
|
||||||
# either django-storage-redux or boto
|
|
||||||
control = 'max-age=%d, s-maxage=%d, must-revalidate' % (AWS_EXPIRY, AWS_EXPIRY)
|
|
||||||
AWS_S3_OBJECT_PARAMETERS = {
|
|
||||||
'CacheControl': bytes(control, encoding='latin-1'),
|
|
||||||
}
|
|
||||||
|
|
||||||
# URL that handles the media served from MEDIA_ROOT, used for managing
|
|
||||||
# stored files.
|
|
||||||
{% if cookiecutter.use_whitenoise == 'y' -%}
|
|
||||||
MEDIA_URL = 'https://s3.amazonaws.com/%s/' % AWS_STORAGE_BUCKET_NAME
|
|
||||||
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
|
|
||||||
{% else %}
|
|
||||||
# See:http://stackoverflow.com/questions/10390244/
|
|
||||||
from storages.backends.s3boto3 import S3Boto3Storage
|
|
||||||
StaticRootS3BotoStorage = lambda: S3Boto3Storage(location='static') # noqa
|
|
||||||
MediaRootS3BotoStorage = lambda: S3Boto3Storage(location='media', file_overwrite=False) # noqa
|
|
||||||
DEFAULT_FILE_STORAGE = 'config.settings.production.MediaRootS3BotoStorage'
|
|
||||||
|
|
||||||
MEDIA_URL = 'https://s3.amazonaws.com/%s/media/' % AWS_STORAGE_BUCKET_NAME
|
|
||||||
{%- endif %}
|
|
||||||
|
|
||||||
# Static Assets
|
|
||||||
# ------------------------
|
|
||||||
{% if cookiecutter.use_whitenoise == 'y' -%}
|
|
||||||
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
|
|
||||||
{% else %}
|
|
||||||
STATIC_URL = 'https://s3.amazonaws.com/%s/static/' % AWS_STORAGE_BUCKET_NAME
|
|
||||||
STATICFILES_STORAGE = 'config.settings.production.StaticRootS3BotoStorage'
|
|
||||||
# See: https://github.com/antonagestam/collectfast
|
|
||||||
# For Django 1.7+, 'collectfast' should come before
|
|
||||||
# 'django.contrib.staticfiles'
|
|
||||||
AWS_PRELOAD_METADATA = True
|
|
||||||
INSTALLED_APPS = ['collectfast', ] + INSTALLED_APPS
|
|
||||||
{%- endif %}
|
|
||||||
{% if cookiecutter.use_compressor == 'y'-%}
|
|
||||||
# COMPRESSOR
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
COMPRESS_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
|
|
||||||
COMPRESS_URL = STATIC_URL
|
|
||||||
COMPRESS_ENABLED = env.bool('COMPRESS_ENABLED', default=True)
|
|
||||||
{%- endif %}
|
|
||||||
# EMAIL
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
DEFAULT_FROM_EMAIL = env('DJANGO_DEFAULT_FROM_EMAIL',
|
|
||||||
default='{{cookiecutter.project_name}} <noreply@{{cookiecutter.domain_name}}>')
|
|
||||||
EMAIL_SUBJECT_PREFIX = env('DJANGO_EMAIL_SUBJECT_PREFIX', default='[{{cookiecutter.project_name}}]')
|
|
||||||
SERVER_EMAIL = env('DJANGO_SERVER_EMAIL', default=DEFAULT_FROM_EMAIL)
|
|
||||||
|
|
||||||
# Anymail with Mailgun
|
|
||||||
INSTALLED_APPS += ['anymail', ]
|
|
||||||
ANYMAIL = {
|
|
||||||
'MAILGUN_API_KEY': env('DJANGO_MAILGUN_API_KEY'),
|
|
||||||
'MAILGUN_SENDER_DOMAIN': env('MAILGUN_SENDER_DOMAIN')
|
|
||||||
}
|
|
||||||
EMAIL_BACKEND = 'anymail.backends.mailgun.EmailBackend'
|
|
||||||
|
|
||||||
# TEMPLATE CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# See:
|
|
||||||
# https://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.loaders.cached.Loader
|
|
||||||
TEMPLATES[0]['OPTIONS']['loaders'] = [
|
|
||||||
('django.template.loaders.cached.Loader', [
|
|
||||||
'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', ]),
|
|
||||||
]
|
|
||||||
{% set _DEFAULT_CONN_MAX_AGE=60 %}
|
|
||||||
# DATABASE CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Use the Heroku-style specification
|
|
||||||
# Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
|
|
||||||
DATABASES['default'] = env.db('DATABASE_URL')
|
|
||||||
DATABASES['default']['CONN_MAX_AGE'] = env.int('CONN_MAX_AGE', default={{ _DEFAULT_CONN_MAX_AGE }})
|
|
||||||
DATABASES['default']['ATOMIC_REQUESTS'] = True
|
|
||||||
|
|
||||||
# CACHING
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
REDIS_LOCATION = '{0}/{1}'.format(env('REDIS_URL', default='redis://127.0.0.1:6379'), 0)
|
|
||||||
|
|
||||||
# Heroku URL does not pass the DB number, so we parse it in
|
|
||||||
CACHES = {
|
CACHES = {
|
||||||
'default': {
|
'default': {
|
||||||
'BACKEND': 'django_redis.cache.RedisCache',
|
'BACKEND': 'django_redis.cache.RedisCache',
|
||||||
'LOCATION': REDIS_LOCATION,
|
'LOCATION': f'{env("REDIS_URL", default="redis://127.0.0.1:6379")}/{0}',
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
|
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
|
||||||
'IGNORE_EXCEPTIONS': True, # mimics memcache behavior.
|
# Mimicing memcache behavior.
|
||||||
# http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior
|
# http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior
|
||||||
|
'IGNORE_EXCEPTIONS': True,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
# SECURITY
|
||||||
# Sentry Configuration
|
# ------------------------------------------------------------------------------
|
||||||
|
# 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/#session-cookie-httponly
|
||||||
|
SESSION_COOKIE_HTTPONLY = True
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-secure
|
||||||
|
CSRF_COOKIE_SECURE = True
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-httponly
|
||||||
|
CSRF_COOKIE_HTTPONLY = 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)
|
||||||
|
# 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'
|
||||||
|
|
||||||
|
# STORAGES
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# https://django-storages.readthedocs.io/en/latest/#installation
|
||||||
|
INSTALLED_APPS += ['storages'] # noqa F405
|
||||||
|
# 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_AUTO_CREATE_BUCKET = True
|
||||||
|
# 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',
|
||||||
|
}
|
||||||
|
|
||||||
|
# STATIC
|
||||||
|
# ------------------------
|
||||||
|
{% if cookiecutter.use_whitenoise == 'y' -%}
|
||||||
|
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
|
||||||
|
{%- else %}
|
||||||
|
STATICFILES_STORAGE = 'config.settings.production.StaticRootS3BotoStorage'
|
||||||
|
STATIC_URL = 'https://s3.amazonaws.com/%s/static/' % AWS_STORAGE_BUCKET_NAME
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
|
# MEDIA
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
{% if cookiecutter.use_whitenoise == 'y' -%}
|
||||||
|
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
|
||||||
|
MEDIA_URL = f'https://s3.amazonaws.com/{AWS_STORAGE_BUCKET_NAME}/'
|
||||||
|
{%- else %}
|
||||||
|
# region http://stackoverflow.com/questions/10390244/
|
||||||
|
from storages.backends.s3boto3 import S3Boto3Storage
|
||||||
|
StaticRootS3BotoStorage = lambda: S3Boto3Storage(location='static') # noqa
|
||||||
|
MediaRootS3BotoStorage = lambda: S3Boto3Storage(location='media', file_overwrite=False) # noqa
|
||||||
|
# endregion
|
||||||
|
DEFAULT_FILE_STORAGE = 'config.settings.production.MediaRootS3BotoStorage'
|
||||||
|
MEDIA_URL = f'https://s3.amazonaws.com/{AWS_STORAGE_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')
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gunicorn
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
INSTALLED_APPS += ['gunicorn'] # noqa F405
|
||||||
|
|
||||||
|
{% if cookiecutter.use_whitenoise == 'y' -%}
|
||||||
|
# WhiteNoise
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# http://whitenoise.evans.io/en/latest/django.html#enable-whitenoise
|
||||||
|
MIDDLEWARE = ['whitenoise.middleware.WhiteNoiseMiddleware'] + MIDDLEWARE # 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
|
||||||
|
|
||||||
|
{%- 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 %}
|
||||||
|
{% if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
||||||
|
# raven
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# https://docs.sentry.io/clients/python/integrations/django/
|
||||||
|
INSTALLED_APPS += ['raven.contrib.django.raven_compat'] # noqa F405
|
||||||
|
MIDDLEWARE = ['raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware'] + MIDDLEWARE
|
||||||
|
|
||||||
|
# Sentry
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
SENTRY_DSN = env('DJANGO_SENTRY_DSN')
|
SENTRY_DSN = env('DJANGO_SENTRY_DSN')
|
||||||
SENTRY_CLIENT = env('DJANGO_SENTRY_CLIENT', default='raven.contrib.django.raven_compat.DjangoClient')
|
SENTRY_CLIENT = env('DJANGO_SENTRY_CLIENT', default='raven.contrib.django.raven_compat.DjangoClient')
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
|
@ -205,7 +192,7 @@ LOGGING = {
|
||||||
'disable_existing_loggers': True,
|
'disable_existing_loggers': True,
|
||||||
'root': {
|
'root': {
|
||||||
'level': 'WARNING',
|
'level': 'WARNING',
|
||||||
'handlers': ['sentry', ],
|
'handlers': ['sentry'],
|
||||||
},
|
},
|
||||||
'formatters': {
|
'formatters': {
|
||||||
'verbose': {
|
'verbose': {
|
||||||
|
@ -227,38 +214,39 @@ LOGGING = {
|
||||||
'loggers': {
|
'loggers': {
|
||||||
'django.db.backends': {
|
'django.db.backends': {
|
||||||
'level': 'ERROR',
|
'level': 'ERROR',
|
||||||
'handlers': ['console', ],
|
'handlers': ['console'],
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
},
|
},
|
||||||
'raven': {
|
'raven': {
|
||||||
'level': 'DEBUG',
|
'level': 'DEBUG',
|
||||||
'handlers': ['console', ],
|
'handlers': ['console'],
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
},
|
},
|
||||||
'sentry.errors': {
|
'sentry.errors': {
|
||||||
'level': 'DEBUG',
|
'level': 'DEBUG',
|
||||||
'handlers': ['console', ],
|
'handlers': ['console'],
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
},
|
},
|
||||||
'django.security.DisallowedHost': {
|
'django.security.DisallowedHost': {
|
||||||
'level': 'ERROR',
|
'level': 'ERROR',
|
||||||
'handlers': ['console', 'sentry', ],
|
'handlers': ['console', 'sentry'],
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
SENTRY_CELERY_LOGLEVEL = env.int('DJANGO_SENTRY_LOG_LEVEL', logging.INFO)
|
SENTRY_CELERY_LOGLEVEL = env.int('DJANGO_SENTRY_LOG_LEVEL', logging.INFO)
|
||||||
RAVEN_CONFIG = {
|
RAVEN_CONFIG = {
|
||||||
'CELERY_LOGLEVEL': env.int('DJANGO_SENTRY_LOG_LEVEL', logging.INFO),
|
'CELERY_LOGLEVEL': env.int('DJANGO_SENTRY_LOG_LEVEL', logging.INFO),
|
||||||
'DSN': SENTRY_DSN
|
'DSN': SENTRY_DSN
|
||||||
}
|
}
|
||||||
{% elif cookiecutter.use_sentry_for_error_reporting == 'n' %}
|
{%- else %}
|
||||||
# LOGGING CONFIGURATION
|
# LOGGING
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#logging
|
# See: https://docs.djangoproject.com/en/dev/ref/settings/#logging
|
||||||
# A sample logging configuration. The only tangible logging
|
# A sample logging configuration. The only tangible logging
|
||||||
# performed by this configuration is to send an email to
|
# performed by this configuration is to send an email to
|
||||||
# the site admins on every HTTP 500 error when DEBUG=False.
|
# the site admins bon every HTTP 500 error when DEBUG=False.
|
||||||
# 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 = {
|
||||||
|
@ -278,7 +266,7 @@ LOGGING = {
|
||||||
'handlers': {
|
'handlers': {
|
||||||
'mail_admins': {
|
'mail_admins': {
|
||||||
'level': 'ERROR',
|
'level': 'ERROR',
|
||||||
'filters': ['require_debug_false', ],
|
'filters': ['require_debug_false'],
|
||||||
'class': 'django.utils.log.AdminEmailHandler'
|
'class': 'django.utils.log.AdminEmailHandler'
|
||||||
},
|
},
|
||||||
'console': {
|
'console': {
|
||||||
|
@ -289,20 +277,33 @@ LOGGING = {
|
||||||
},
|
},
|
||||||
'loggers': {
|
'loggers': {
|
||||||
'django.request': {
|
'django.request': {
|
||||||
'handlers': ['mail_admins', ],
|
'handlers': ['mail_admins'],
|
||||||
'level': 'ERROR',
|
'level': 'ERROR',
|
||||||
'propagate': True
|
'propagate': True
|
||||||
},
|
},
|
||||||
'django.security.DisallowedHost': {
|
'django.security.DisallowedHost': {
|
||||||
'level': 'ERROR',
|
'level': 'ERROR',
|
||||||
'handlers': ['console', 'mail_admins', ],
|
'handlers': ['console', 'mail_admins'],
|
||||||
'propagate': True
|
'propagate': True
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{% endif %}
|
|
||||||
# Custom Admin URL, use {% raw %}{% url 'admin:index' %}{% endraw %}
|
|
||||||
ADMIN_URL = env('DJANGO_ADMIN_URL')
|
|
||||||
|
|
||||||
# Your production stuff: Below this line define 3rd party library settings
|
{%- endif %}
|
||||||
|
{% if cookiecutter.use_opbeat == 'y' -%}
|
||||||
|
# opbeat
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# https://opbeat.com/docs/articles/get-started-with-django/#setup
|
||||||
|
INSTALLED_APPS += ['opbeat.contrib.django'] # noqa F405
|
||||||
|
# https://opbeat.com/docs/articles/get-started-with-django/#setup
|
||||||
|
OPBEAT = {
|
||||||
|
'ORGANIZATION_ID': env('DJANGO_OPBEAT_ORGANIZATION_ID'),
|
||||||
|
'APP_ID': env('DJANGO_OPBEAT_APP_ID'),
|
||||||
|
'SECRET_TOKEN': env('DJANGO_OPBEAT_SECRET_TOKEN')
|
||||||
|
}
|
||||||
|
# https://opbeat.com/docs/articles/get-started-with-django/#performance-metrics
|
||||||
|
MIDDLEWARE = ['opbeat.contrib.django.middleware.OpbeatAPMMiddleware'] + MIDDLEWARE
|
||||||
|
|
||||||
|
{%- endif %}
|
||||||
|
# Your stuff...
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,36 +1,22 @@
|
||||||
"""
|
"""
|
||||||
Test settings for {{cookiecutter.project_name}} project.
|
With these settings, tests run faster.
|
||||||
|
|
||||||
- Used to run tests fast on the continuous integration server and locally
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .base import * # noqa
|
from .base import * # noqa
|
||||||
|
from .base import env
|
||||||
|
|
||||||
|
# GENERAL
|
||||||
# DEBUG
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Turn debug off so tests run faster
|
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
TEMPLATES[0]['OPTIONS']['debug'] = False
|
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
||||||
|
|
||||||
# SECRET CONFIGURATION
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
|
||||||
# Note: This key only used for development and testing.
|
|
||||||
SECRET_KEY = env('DJANGO_SECRET_KEY', default='!!!SET DJANGO_SECRET_KEY!!!')
|
SECRET_KEY = env('DJANGO_SECRET_KEY', default='!!!SET DJANGO_SECRET_KEY!!!')
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#test-runner
|
||||||
|
TEST_RUNNER = 'django.test.runner.DiscoverRunner'
|
||||||
|
|
||||||
# Mail settings
|
# CACHES
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
EMAIL_HOST = 'localhost'
|
# https://docs.djangoproject.com/en/dev/ref/settings/#caches
|
||||||
EMAIL_PORT = 1025
|
|
||||||
|
|
||||||
# In-memory email backend stores messages in django.core.mail.outbox
|
|
||||||
# for unit testing purposes
|
|
||||||
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
|
|
||||||
|
|
||||||
# CACHING
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Speed advantages of in-memory caching without having to run Memcached
|
|
||||||
CACHES = {
|
CACHES = {
|
||||||
'default': {
|
'default': {
|
||||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||||
|
@ -38,24 +24,35 @@ CACHES = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# TESTING
|
# PASSWORDS
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
TEST_RUNNER = 'django.test.runner.DiscoverRunner'
|
# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers
|
||||||
|
|
||||||
|
|
||||||
# PASSWORD HASHING
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Use fast password hasher so tests run faster
|
|
||||||
PASSWORD_HASHERS = [
|
PASSWORD_HASHERS = [
|
||||||
'django.contrib.auth.hashers.MD5PasswordHasher',
|
'django.contrib.auth.hashers.MD5PasswordHasher',
|
||||||
]
|
]
|
||||||
|
|
||||||
# TEMPLATE LOADERS
|
# TEMPLATES
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Keep templates in memory so tests run faster
|
# https://docs.djangoproject.com/en/dev/ref/settings/#templates
|
||||||
TEMPLATES[0]['OPTIONS']['loaders'] = [
|
TEMPLATES[0]['OPTIONS']['debug'] = DEBUG # noqa F405
|
||||||
['django.template.loaders.cached.Loader', [
|
TEMPLATES[0]['OPTIONS']['loaders'] = [ # noqa F405
|
||||||
'django.template.loaders.filesystem.Loader',
|
(
|
||||||
'django.template.loaders.app_directories.Loader',
|
'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/#email-backend
|
||||||
|
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#email-host
|
||||||
|
EMAIL_HOST = 'localhost'
|
||||||
|
# https://docs.djangoproject.com/en/dev/ref/settings/#email-port
|
||||||
|
EMAIL_PORT = 1025
|
||||||
|
|
||||||
|
# Your stuff...
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -4,6 +4,9 @@ POSTGRES_PASSWORD=!!!SET POSTGRES_PASSWORD!!!
|
||||||
POSTGRES_USER=!!!SET POSTGRES_USER!!!
|
POSTGRES_USER=!!!SET POSTGRES_USER!!!
|
||||||
CONN_MAX_AGE=
|
CONN_MAX_AGE=
|
||||||
|
|
||||||
|
# Gunicorn concurrency
|
||||||
|
WEB_CONCURRENCY=4
|
||||||
|
|
||||||
# Domain name, used by caddy
|
# Domain name, used by caddy
|
||||||
DOMAIN_NAME={{ cookiecutter.domain_name }}
|
DOMAIN_NAME={{ cookiecutter.domain_name }}
|
||||||
|
|
||||||
|
@ -20,9 +23,9 @@ DJANGO_AWS_SECRET_ACCESS_KEY=
|
||||||
DJANGO_AWS_STORAGE_BUCKET_NAME=
|
DJANGO_AWS_STORAGE_BUCKET_NAME=
|
||||||
|
|
||||||
# Used with email
|
# Used with email
|
||||||
DJANGO_MAILGUN_API_KEY=
|
MAILGUN_API_KEY=
|
||||||
DJANGO_SERVER_EMAIL=
|
DJANGO_SERVER_EMAIL=
|
||||||
MAILGUN_SENDER_DOMAIN=
|
MAILGUN_DOMAIN=
|
||||||
|
|
||||||
# Security! Better to use DNS for this task, but you can use redirect
|
# Security! Better to use DNS for this task, but you can use redirect
|
||||||
DJANGO_SECURE_SSL_REDIRECT=False
|
DJANGO_SECURE_SSL_REDIRECT=False
|
||||||
|
|
6
{{cookiecutter.project_slug}}/locale/README.rst
Normal file
6
{{cookiecutter.project_slug}}/locale/README.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Translations
|
||||||
|
============
|
||||||
|
|
||||||
|
Translations will be placed in this folder when running::
|
||||||
|
|
||||||
|
python manage.py makemessages
|
|
@ -4,22 +4,22 @@
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
{% if cookiecutter.js_task_runner == 'Grunt' %}
|
{% if cookiecutter.js_task_runner == 'Grunt' %}
|
||||||
"autoprefixer-core": "~5.2.1",
|
"autoprefixer": "~8.1.0",
|
||||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||||
"bootstrap": "^4.0.0",
|
"bootstrap": "^4.0.0",
|
||||||
{% endif %}
|
{% endif %}
|
||||||
"connect-livereload": "~0.3.2",
|
"connect-livereload": "~0.6.0",
|
||||||
"cssnano": "~2.1.0",
|
"cssnano": "~3.10.0",
|
||||||
"grunt": "~0.4.5",
|
"grunt": "~1.0.2",
|
||||||
"grunt-bg-shell": "~2.3.1",
|
"grunt-bg-shell": "~2.3.1",
|
||||||
"grunt-contrib-watch": "~0.6.1",
|
"grunt-contrib-watch": "~1.0.0",
|
||||||
"grunt-postcss": "~0.5.5",
|
"grunt-postcss": "~0.9.0",
|
||||||
"grunt-sass": "~1.0.0",
|
"grunt-sass": "~2.1.0",
|
||||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||||
"jquery": "^3.2.1-slim",
|
"jquery": "^3.2.1-slim",
|
||||||
{% endif %}
|
{% endif %}
|
||||||
"load-grunt-tasks": "~3.2.0",
|
"load-grunt-tasks": "~3.2.0",
|
||||||
"pixrem": "~1.3.1",
|
"pixrem": "~4.0.1",
|
||||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||||
"popper.js": "^1.12.3",
|
"popper.js": "^1.12.3",
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -31,26 +31,34 @@
|
||||||
"browser-sync": "^2.14.0",
|
"browser-sync": "^2.14.0",
|
||||||
"del": "^2.2.2",
|
"del": "^2.2.2",
|
||||||
"gulp": "^3.9.1",
|
"gulp": "^3.9.1",
|
||||||
"gulp-autoprefixer": "^3.1.1",
|
"gulp-autoprefixer": "^5.0.0",
|
||||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||||
"gulp-concat": "^2.6.1",
|
"gulp-concat": "^2.6.1",
|
||||||
{% endif %}
|
{% endif %}
|
||||||
"gulp-cssnano": "^2.1.2",
|
"gulp-cssnano": "^2.1.2",
|
||||||
"gulp-imagemin": "^3.0.3",
|
"gulp-imagemin": "^4.1.0",
|
||||||
"gulp-pixrem": "^1.0.0",
|
"gulp-pixrem": "^1.0.0",
|
||||||
"gulp-plumber": "^1.1.0",
|
"gulp-plumber": "^1.1.0",
|
||||||
"gulp-rename": "^1.2.2",
|
"gulp-rename": "^1.2.2",
|
||||||
"gulp-sass": "^2.3.2",
|
"gulp-sass": "^3.1.0",
|
||||||
"gulp-uglify": "^2.0.0",
|
"gulp-uglify": "^3.0.0",
|
||||||
"gulp-util": "^3.0.7",
|
"gulp-util": "^3.0.7",
|
||||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||||
"jquery": "^3.2.1-slim",
|
"jquery": "^3.2.1-slim",
|
||||||
"popper.js": "^1.12.3",
|
"popper.js": "^1.12.3",
|
||||||
{% endif %}
|
{% endif %}
|
||||||
"run-sequence": "^1.2.2"
|
"run-sequence": "^2.1.1"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
{% if cookiecutter.js_task_runner == 'Grunt' %}
|
||||||
|
"dev": "grunt serve"
|
||||||
|
{% elif cookiecutter.js_task_runner == 'Gulp' %}
|
||||||
|
"dev": "gulp"
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
# This file is here because many Platforms as a Service look for
|
# This file is expected by Heroku.
|
||||||
# requirements.txt in the root directory of a project.
|
|
||||||
-r requirements/production.txt
|
-r requirements/production.txt
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
# Wheel 0.25+ needed to install certain packages on CPython 3.5+
|
|
||||||
# like Pillow and psycopg2
|
|
||||||
# See http://bitly.com/wheel-building-fails-CPython-35
|
|
||||||
# Verified bug on Python 3.5.1
|
|
||||||
wheel==0.30.0
|
|
||||||
|
|
||||||
|
|
||||||
# Conservative Django
|
# Conservative Django
|
||||||
django==2.0.2 # pyup: < 2.1
|
django==2.0.3 # pyup: < 2.1
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
django-environ==0.4.4
|
django-environ==0.4.4
|
||||||
|
@ -16,7 +9,7 @@ whitenoise==3.3.1
|
||||||
|
|
||||||
|
|
||||||
# Forms
|
# Forms
|
||||||
django-crispy-forms==1.7.0
|
django-crispy-forms==1.7.1
|
||||||
|
|
||||||
# Models
|
# Models
|
||||||
django-model-utils==3.1.1
|
django-model-utils==3.1.1
|
||||||
|
@ -36,7 +29,7 @@ django-allauth==0.35.0
|
||||||
# from http://www.lfd.uci.edu/~gohlke/pythonlibs/#psycopg
|
# from http://www.lfd.uci.edu/~gohlke/pythonlibs/#psycopg
|
||||||
{% else %}
|
{% else %}
|
||||||
# Python-PostgreSQL Database Adapter
|
# Python-PostgreSQL Database Adapter
|
||||||
psycopg2==2.7.4
|
psycopg2==2.7.4 --no-binary psycopg2
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
# Unicode slugification
|
# Unicode slugification
|
||||||
|
@ -46,7 +39,7 @@ awesome-slugify==1.6.5
|
||||||
pytz==2018.3
|
pytz==2018.3
|
||||||
|
|
||||||
# Redis support
|
# Redis support
|
||||||
django-redis==4.8.0
|
django-redis==4.9.0
|
||||||
redis>=2.10.5
|
redis>=2.10.5
|
||||||
|
|
||||||
{% if cookiecutter.use_celery == "y" %}
|
{% if cookiecutter.use_celery == "y" %}
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
coverage==4.5.1
|
coverage==4.5.1
|
||||||
django-coverage-plugin==1.5.0
|
django-coverage-plugin==1.5.0
|
||||||
|
|
||||||
Sphinx==1.7.0
|
Sphinx==1.7.1
|
||||||
django-extensions==1.9.9
|
django-extensions==2.0.0
|
||||||
Werkzeug==0.14.1
|
Werkzeug==0.14.1
|
||||||
django-test-plus==1.0.22
|
django-test-plus==1.0.22
|
||||||
factory-boy==2.10.0
|
factory-boy==2.10.0
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
# Python-PostgreSQL Database Adapter
|
# Python-PostgreSQL Database Adapter
|
||||||
# Assuming Windows is used locally, and *nix -- in production.
|
# Assuming Windows is used locally, and *nix -- in production.
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
psycopg2==2.7.4
|
psycopg2==2.7.4 --no-binary psycopg2
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
# WSGI Handler
|
# WSGI Handler
|
||||||
|
@ -16,7 +16,7 @@ gunicorn==19.7.1
|
||||||
|
|
||||||
# Static and Media Storage
|
# Static and Media Storage
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
boto3==1.5.31
|
boto3==1.6.2 # pyup: update minor
|
||||||
django-storages==1.6.5
|
django-storages==1.6.5
|
||||||
{% if cookiecutter.use_whitenoise != 'y' -%}
|
{% if cookiecutter.use_whitenoise != 'y' -%}
|
||||||
Collectfast==0.6.0
|
Collectfast==0.6.0
|
||||||
|
@ -29,7 +29,7 @@ django-anymail==1.4
|
||||||
{% if cookiecutter.use_sentry_for_error_reporting == "y" -%}
|
{% if cookiecutter.use_sentry_for_error_reporting == "y" -%}
|
||||||
# Raven is the Sentry client
|
# Raven is the Sentry client
|
||||||
# --------------------------
|
# --------------------------
|
||||||
raven==6.5.0
|
raven==6.6.0
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{% if cookiecutter.use_opbeat == "y" -%}
|
{% if cookiecutter.use_opbeat == "y" -%}
|
||||||
|
|
|
@ -66,7 +66,7 @@ class CeleryConfig(AppConfig):
|
||||||
try:
|
try:
|
||||||
opbeat_register_signal(opbeat_client)
|
opbeat_register_signal(opbeat_client)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
opbeat_logger.exception('Failed installing celery hook: %s' % e)
|
opbeat_logger.exception(f'Failed installing celery hook: {e}')
|
||||||
|
|
||||||
if 'opbeat.contrib.django' in settings.INSTALLED_APPS:
|
if 'opbeat.contrib.django' in settings.INSTALLED_APPS:
|
||||||
opbeat_register_handlers()
|
opbeat_register_handlers()
|
||||||
|
@ -75,7 +75,7 @@ class CeleryConfig(AppConfig):
|
||||||
|
|
||||||
@app.task(bind=True)
|
@app.task(bind=True)
|
||||||
def debug_task(self):
|
def debug_task(self):
|
||||||
print('Request: {0!r}'.format(self.request)) # pragma: no cover
|
print(f'Request: {self.request!r}') # pragma: no cover
|
||||||
{% else %}
|
{% else %}
|
||||||
# Use this as a starting point for your project with celery.
|
# Use this as a starting point for your project with celery.
|
||||||
# If you are not using celery, you can remove this app
|
# If you are not using celery, you can remove this app
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<!-- 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" %}{% raw %}
|
{% endraw %}{% if cookiecutter.js_task_runner == "Gulp" and 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">
|
||||||
|
|
|
@ -10,4 +10,7 @@ class UsersConfig(AppConfig):
|
||||||
Users system checks
|
Users system checks
|
||||||
Users signal registration
|
Users signal registration
|
||||||
"""
|
"""
|
||||||
pass
|
try:
|
||||||
|
import users.signals # noqa F401
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.encoding import python_2_unicode_compatible
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class User(AbstractUser):
|
class User(AbstractUser):
|
||||||
|
|
||||||
# First Name and Last Name do not cover name patterns
|
# First Name and Last Name do not cover name patterns
|
||||||
|
|
|
@ -2,8 +2,8 @@ import factory
|
||||||
|
|
||||||
|
|
||||||
class UserFactory(factory.django.DjangoModelFactory):
|
class UserFactory(factory.django.DjangoModelFactory):
|
||||||
username = factory.Sequence(lambda n: 'user-{0}'.format(n))
|
username = factory.Sequence(lambda n: f'user-{n}')
|
||||||
email = factory.Sequence(lambda n: 'user-{0}@example.com'.format(n))
|
email = factory.Sequence(lambda n: f'user-{n}@example.com')
|
||||||
password = factory.PostGenerationMethodCall('set_password', 'password')
|
password = factory.PostGenerationMethodCall('set_password', 'password')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -14,14 +14,14 @@ urlpatterns = [
|
||||||
view=views.UserRedirectView.as_view(),
|
view=views.UserRedirectView.as_view(),
|
||||||
name='redirect'
|
name='redirect'
|
||||||
),
|
),
|
||||||
url(
|
|
||||||
regex=r'^(?P<username>[\w.@+-]+)/$',
|
|
||||||
view=views.UserDetailView.as_view(),
|
|
||||||
name='detail'
|
|
||||||
),
|
|
||||||
url(
|
url(
|
||||||
regex=r'^~update/$',
|
regex=r'^~update/$',
|
||||||
view=views.UserUpdateView.as_view(),
|
view=views.UserUpdateView.as_view(),
|
||||||
name='update'
|
name='update'
|
||||||
),
|
),
|
||||||
|
url(
|
||||||
|
regex=r'^(?P<username>[\w.@+-]+)/$',
|
||||||
|
view=views.UserDetailView.as_view(),
|
||||||
|
name='detail'
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user