mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-08-08 14:04:52 +03:00
Merge branch 'master' into adopt-a-better-approach-to-env-variable-handing-with-docker
This commit is contained in:
commit
0cb3bd202a
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -226,3 +226,5 @@ pip-selfcheck.json
|
|||
# to 'run' anything within it since any particular cookiecutter
|
||||
# is declarative by nature.
|
||||
.idea/
|
||||
|
||||
.pytest_cache/
|
||||
|
|
14
.travis.yml
14
.travis.yml
|
@ -7,22 +7,12 @@ services:
|
|||
|
||||
language: python
|
||||
|
||||
python: 3.5
|
||||
python: 3.6
|
||||
|
||||
env:
|
||||
- TOX_ENV=py34
|
||||
- TOX_ENV=py35
|
||||
- TOX_ENV=py36
|
||||
|
||||
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 -v
|
||||
|
||||
|
|
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -2,11 +2,23 @@
|
|||
All enhancements and patches to Cookiecutter Django will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [2015-10-08]
|
||||
## [2018-02-16]
|
||||
### Changed
|
||||
- Upgraded to Django 2.0 (@epicwhale)
|
||||
|
||||
## [2018-01-15]
|
||||
### Changed
|
||||
- Removed Elastic Beanstalk support (@pydanny)
|
||||
|
||||
## [2017-12-28]
|
||||
### Changed
|
||||
- Upgraded to Django 1.11 (@pydanny)
|
||||
|
||||
## [2017-10-08]
|
||||
### Changed
|
||||
- Elastic Beanstalk: Added --noinput to migrate command (@MightySCollins )
|
||||
|
||||
## [2015-10-07]
|
||||
## [2017-10-07]
|
||||
### Added
|
||||
- Finished first pass at Elastic Beanstalk docs (@pydanny & @audreyr)
|
||||
### Deleted
|
||||
|
|
|
@ -36,13 +36,12 @@ To run all tests using various versions of python in virtualenvs defined in tox.
|
|||
|
||||
$ tox
|
||||
|
||||
It is possible to tests with some versions of python, to do this the command
|
||||
It is possible to test with a specific version of python. To do this, the command
|
||||
is::
|
||||
|
||||
$ tox -e py34,py35
|
||||
$ tox -e py36
|
||||
|
||||
Will run py.test with the python3.4, and python3.5 interpreters, for
|
||||
example.
|
||||
This will run py.test with the python3.6 interpreter, for example.
|
||||
|
||||
To run a particular test with tox for against your current Python version::
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@ Core Developers
|
|||
These contributors have commit flags for the repository,
|
||||
and are able to accept and merge pull requests.
|
||||
|
||||
=========================== ============= ===========
|
||||
=========================== ================ ===========
|
||||
Name Github Twitter
|
||||
=========================== ============= ===========
|
||||
=========================== ================ ===========
|
||||
Daniel Roy Greenfeld `@pydanny`_ @pydanny
|
||||
Audrey Roy Greenfeld* `@audreyr`_ @audreyr
|
||||
Fábio C. Barrionuevo da Luz `@luzfcb`_ @luzfcb
|
||||
|
@ -17,7 +17,8 @@ Saurabh Kumar `@theskumar`_ @_theskumar
|
|||
Jannis Gebauer `@jayfk`_
|
||||
Burhan Khalid `@burhan`_ @burhan
|
||||
Shupeyko Nikita `@webyneter`_ @webyneter
|
||||
=========================== ============= ===========
|
||||
Bruno Alla `@browniebroke`_ @_BrunoAlla
|
||||
=========================== ================ ===========
|
||||
|
||||
*Audrey is also the creator of Cookiecutter. Audrey and
|
||||
Daniel are on the Cookiecutter core team.*
|
||||
|
@ -28,6 +29,7 @@ Daniel are on the Cookiecutter core team.*
|
|||
.. _@audreyr: https://github.com/audreyr
|
||||
.. _@jayfk: https://github.com/jayfk
|
||||
.. _@webyneter: https://github.com/webyneter
|
||||
.. _@browniebroke: https://github.com/browniebroke
|
||||
|
||||
Other Contributors
|
||||
------------------
|
||||
|
@ -42,6 +44,7 @@ Listed in alphabetical order.
|
|||
Aaron Eikenberry `@aeikenberry`_
|
||||
Adam Bogdał `@bogdal`_
|
||||
Adam Dobrawy `@ad-m`_
|
||||
Adam Steele `@adammsteele`
|
||||
Agam Dua
|
||||
Alberto Sanchez `@alb3rto`_
|
||||
Alex Tsai `@caffodian`_
|
||||
|
@ -64,7 +67,6 @@ Listed in alphabetical order.
|
|||
Bo Lopker `@blopker`_
|
||||
Bouke Haarsma
|
||||
Brent Payne `@brentpayne`_ @brentpayne
|
||||
Bruno Alla `@browniebroke`_ @_BrunoAlla
|
||||
Burhan Khalid `@burhan`_ @burhan
|
||||
Catherine Devlin `@catherinedevlin`_
|
||||
Cédric Gaspoz `@cgaspoz`_
|
||||
|
@ -127,6 +129,7 @@ Listed in alphabetical order.
|
|||
Pablo `@oubiga`_
|
||||
Parbhat Puri `@parbhat`_
|
||||
Peter Bittner `@bittner`_
|
||||
Pierre Chiquet `@pchiquet`_
|
||||
Raphael Pierzina `@hackebrot`_
|
||||
Raony Guimarães Corrêa `@raonyguimaraes`_
|
||||
Reggie Riser `@reggieriser`_
|
||||
|
@ -157,6 +160,7 @@ Listed in alphabetical order.
|
|||
|
||||
.. _@a7p: https://github.com/a7p
|
||||
.. _@ad-m: https://github.com/ad-m
|
||||
.. _@adammsteele: https://github.com/adammsteele
|
||||
.. _@aeikenberry: https://github.com/aeikenberry
|
||||
.. _@alb3rto: https://github.com/alb3rto
|
||||
.. _@ameistad: https://github.com/ameistad
|
||||
|
@ -170,7 +174,6 @@ Listed in alphabetical order.
|
|||
.. _@bloodpet: https://github.com/bloodpet
|
||||
.. _@blopker: https://github.com/blopker
|
||||
.. _@bogdal: https://github.com/bogdal
|
||||
.. _@browniebroke: https://github.com/browniebroke
|
||||
.. _@burhan: https://github.com/burhan
|
||||
.. _@c-rhodes: https://github.com/c-rhodes
|
||||
.. _@caffodian: https://github.com/caffodian
|
||||
|
@ -227,7 +230,6 @@ Listed in alphabetical order.
|
|||
.. _@rm--: https://github.com/rm--
|
||||
.. _@romanosipenko: https://github.com/romanosipenko
|
||||
.. _@shireenrao: https://github.com/shireenrao
|
||||
.. _@webyneter: https://github.com/webyneter
|
||||
.. _@show0k: https://github.com/show0k
|
||||
.. _@sfdye: https://github.com/sfdye
|
||||
.. _@shultz: https://github.com/shultz
|
||||
|
@ -239,7 +241,7 @@ Listed in alphabetical order.
|
|||
.. _@timfreund: https://github.com/timfreund
|
||||
.. _@Travistock: https://github.com/Tavistock
|
||||
.. _@trungdong: https://github.com/trungdong
|
||||
.. _@viviangb: httpsL//github.com/viviangb
|
||||
.. _@viviangb: https://github.com/viviangb
|
||||
.. _@xpostudio4: https://github.com/xpostudio4
|
||||
.. _@yunti: https://github.com/yunti
|
||||
.. _@zcho: https://github.com/zcho
|
||||
|
@ -249,6 +251,12 @@ Listed in alphabetical order.
|
|||
.. _@jangeador: https://github.com/jangeador
|
||||
.. _@townie: https://github.com/townie
|
||||
.. _@MightySCollins: https://github.com/MightySCollins
|
||||
.. _@dadokkio: https://github.com/dadokkio
|
||||
.. _@bwarren2: https://github.com/bwarren2
|
||||
.. _@bertdemiranda: https://github.com/bertdemiranda
|
||||
.. _@brentpayne: https://github.com/brentpayne
|
||||
.. _@afrowave: https://github.com/afrowave
|
||||
.. _@pchiquet: https://github.com/pchiquet
|
||||
|
||||
Special Thanks
|
||||
~~~~~~~~~~~~~~
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2013-2016, Daniel Greenfeld
|
||||
Copyright (c) 2013-2018, Daniel Greenfeld
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
|
39
README.rst
39
README.rst
|
@ -12,6 +12,10 @@ Cookiecutter Django
|
|||
.. image:: https://badges.gitter.im/Join Chat.svg
|
||||
:target: https://gitter.im/pydanny/cookiecutter-django?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
||||
|
||||
.. image:: https://www.codetriage.com/pydanny/cookiecutter-django/badges/users.svg
|
||||
:target: https://www.codetriage.com/pydanny/cookiecutter-django
|
||||
:alt: Code Helpers Badge
|
||||
|
||||
Powered by Cookiecutter_, Cookiecutter Django is a framework for jumpstarting
|
||||
production-ready Django projects quickly.
|
||||
|
||||
|
@ -34,10 +38,10 @@ production-ready Django projects quickly.
|
|||
Features
|
||||
---------
|
||||
|
||||
* For Django 1.10
|
||||
* Works with Python 3.4.x or 3.5.x. Python 3.6 is experimental
|
||||
* For Django 2.0
|
||||
* Works with Python 3.6
|
||||
* 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_
|
||||
* Secure by default. We believe in SSL.
|
||||
* Optimized development and production settings
|
||||
|
@ -51,7 +55,6 @@ Features
|
|||
* Instructions for deploying to PythonAnywhere_
|
||||
* Run tests with unittest or py.test
|
||||
* Customizable PostgreSQL version
|
||||
* Experimental support for Amazon Elastic Beanstalk
|
||||
|
||||
.. _`maintained Foundation fork`: https://github.com/Parbhat/cookiecutter-django-foundation
|
||||
|
||||
|
@ -108,7 +111,7 @@ Two Scoops of Django 1.11
|
|||
:name: Two Scoops of Django 1.11 Cover
|
||||
:align: center
|
||||
: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
|
||||
|
||||
|
@ -168,16 +171,20 @@ Answer the prompts with your own desired options_. For example::
|
|||
use_heroku [n]: y
|
||||
use_compressor [n]: y
|
||||
Select postgresql_version:
|
||||
1 - 9.5
|
||||
2 - 9.4
|
||||
3 - 9.3
|
||||
4 - 9.2
|
||||
1 - 10.3
|
||||
2 - 10.2
|
||||
3 - 10.1
|
||||
4 - 9.6
|
||||
5 - 9.5
|
||||
6 - 9.4
|
||||
7 - 9.3
|
||||
Choose from 1, 2, 3, 4 [1]: 1
|
||||
Select js_task_runner:
|
||||
1 - Gulp
|
||||
2 - Grunt
|
||||
3 - None
|
||||
Choose from 1, 2, 3, 4 [1]: 1
|
||||
custom_bootstrap_compilation [n]: n
|
||||
Select open_source_license:
|
||||
1 - MIT
|
||||
2 - BSD
|
||||
|
@ -185,7 +192,6 @@ Answer the prompts with your own desired options_. For example::
|
|||
4 - Apache Software License 2.0
|
||||
5 - Not open source
|
||||
Choose from 1, 2, 3, 4, 5 [1]: 1
|
||||
use_elasticbeanstalk_experimental: n
|
||||
|
||||
Enter the project and take a look around::
|
||||
|
||||
|
@ -222,7 +228,7 @@ Community
|
|||
.. _`issue`: https://github.com/pydanny/cookiecutter-django/issues
|
||||
.. _`Gitter`: https://gitter.im/pydanny/cookiecutter-django?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
||||
|
||||
For Readers of Two Scoops of Django 1.8
|
||||
For Readers of Two Scoops of Django
|
||||
--------------------------------------------
|
||||
|
||||
You may notice that some elements of this project do not exactly match what we describe in chapter 3. The reason for that is this project, amongst other things, serves as a test bed for trying out new ideas and concepts. Sometimes they work, sometimes they don't, but the end result is that it won't necessarily match precisely what is described in the book I co-authored.
|
||||
|
@ -274,14 +280,21 @@ experience better.
|
|||
Articles
|
||||
---------
|
||||
|
||||
* `Deploying Cookiecutter-Django with Docker-Compose`_ - Oct. 19, 2017
|
||||
* `Using Cookiecutter to Jumpstart a Django Project on Windows with PyCharm`_ - May 19, 2017
|
||||
* `Exploring with Cookiecutter`_ - Dec. 3, 2016
|
||||
* `Introduction to Cookiecutter-Django`_ - Feb. 19, 2016
|
||||
* `Django and GitLab - Running Continuous Integration and tests with your FREE account`_ - May. 11, 2016
|
||||
* `Development and Deployment of Cookiecutter-Django on Fedora`_ - Jan. 18, 2016
|
||||
* `Development and Deployment of Cookiecutter-Django via Docker`_ - Dec. 29, 2015
|
||||
* `How to create a Django Application using Cookiecutter and Django 1.8`_ - Sept. 12, 2015
|
||||
* `Introduction to Cookiecutter-Django`_ - Feb. 19, 2016
|
||||
* `Django and GitLab - Running Continuous Integration and tests with your FREE account`_ - May. 11, 2016
|
||||
|
||||
Have a blog or online publication? Write about your cookiecutter-django tips and tricks, then send us a pull request with the link.
|
||||
|
||||
.. _`Deploying Cookiecutter-Django with Docker-Compose`: http://adamantine.me/2017/10/19/deploying-cookiecutter-django-with-docker-compose/
|
||||
.. _`Exploring with Cookiecutter`: http://www.snowboardingcoder.com/django/2016/12/03/exploring-with-cookiecutter/
|
||||
.. _`Using Cookiecutter to Jumpstart a Django Project on Windows with PyCharm`: https://joshuahunter.com/posts/using-cookiecutter-to-jumpstart-a-django-project-on-windows-with-pycharm/
|
||||
|
||||
.. _`Development and Deployment of Cookiecutter-Django via Docker`: https://realpython.com/blog/python/development-and-deployment-of-cookiecutter-django-via-docker/
|
||||
.. _`Development and Deployment of Cookiecutter-Django on Fedora`: https://realpython.com/blog/python/development-and-deployment-of-cookiecutter-django-on-fedora/
|
||||
.. _`How to create a Django Application using Cookiecutter and Django 1.8`: https://www.swapps.io/blog/how-to-create-a-django-application-using-cookiecutter-and-django-1-8/
|
||||
|
|
|
@ -1,25 +1,43 @@
|
|||
{
|
||||
"project_name": "Project Name",
|
||||
"project_name": "My Awesome Project",
|
||||
"project_slug": "{{ cookiecutter.project_name.lower()|replace(' ', '_')|replace('-', '_') }}",
|
||||
"description": "Behold My Awesome Project!",
|
||||
"author_name": "Daniel Roy Greenfeld",
|
||||
"email": "you@example.com",
|
||||
"description": "A short description of the project.",
|
||||
"email": "{{ cookiecutter.author_name.lower()|replace(' ', '-') }}@example.com",
|
||||
"domain_name": "example.com",
|
||||
"version": "0.1.0",
|
||||
"open_source_license": [
|
||||
"MIT",
|
||||
"BSD",
|
||||
"GPLv3",
|
||||
"Apache Software License 2.0",
|
||||
"Not open source"
|
||||
],
|
||||
"timezone": "UTC",
|
||||
"use_whitenoise": "y",
|
||||
"windows": "n",
|
||||
"use_pycharm": "n",
|
||||
"use_docker": "n",
|
||||
"postgresql_version": [
|
||||
"10.3",
|
||||
"10.2",
|
||||
"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_pycharm": "n",
|
||||
"windows": "n",
|
||||
"use_docker": "n",
|
||||
"use_whitenoise": "y",
|
||||
"use_heroku": "n",
|
||||
"use_elasticbeanstalk_experimental": "n",
|
||||
"use_compressor": "n",
|
||||
"postgresql_version": ["9.6", "9.5", "9.4", "9.3", "9.2"],
|
||||
"js_task_runner": ["Gulp", "Grunt", "None"],
|
||||
"custom_bootstrap_compilation": "n",
|
||||
"open_source_license": ["MIT", "BSD", "GPLv3", "Apache Software License 2.0", "Not open source"]
|
||||
"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 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_SETTINGS_MODULE='config.settings.production'
|
||||
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_STORAGE_BUCKET_NAME=YOUR_AWS_S3_BUCKET_NAME_HERE
|
||||
|
||||
heroku config:set DJANGO_MAILGUN_SERVER_NAME=YOUR_MALGUN_SERVER
|
||||
heroku config:set DJANGO_MAILGUN_API_KEY=YOUR_MAILGUN_API_KEY
|
||||
heroku config:set MAILGUN_SENDER_DOMAIN=YOUR_MAILGUN_SENDER_DOMAIN
|
||||
# This is to be set only if you're using Sentry:
|
||||
heroku config:set DJANGO_SENTRY_DSN=YOUR_SENTRY_DSN
|
||||
|
||||
heroku config:set PYTHONHASHSEED=random
|
||||
heroku config:set DJANGO_ADMIN_URL=\^somelocation/
|
||||
|
||||
git push heroku master
|
||||
heroku run python manage.py migrate
|
||||
|
|
|
@ -35,7 +35,7 @@ Make sure your project is fully commited and pushed up to Bitbucket or Github or
|
|||
|
||||
git clone <my-repo-url> # you can also use hg
|
||||
cd my-project-name
|
||||
mkvirtualenv --python=/usr/bin/python3.5 my-project-name
|
||||
mkvirtualenv --python=/usr/bin/python3.6 my-project-name
|
||||
pip install -r requirements/production.txt # may take a few minutes
|
||||
|
||||
|
||||
|
@ -63,13 +63,13 @@ Add these exports
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
export WEB_CONCURRENCY=4
|
||||
export DJANGO_SETTINGS_MODULE='config.settings.production'
|
||||
export DJANGO_SECRET_KEY='<secret key goes here>'
|
||||
export DJANGO_ALLOWED_HOSTS='<www.your-domain.com>'
|
||||
export DJANGO_ADMIN_URL='<not admin/>'
|
||||
export DJANGO_MAILGUN_API_KEY='<mailgun key>'
|
||||
export DJANGO_MAILGUN_SERVER_NAME='<mailgun server name>'
|
||||
export MAILGUN_SENDER_DOMAIN='<mailgun sender domain (e.g. mg.yourdomain.com)>'
|
||||
export MAILGUN_API_KEY='<mailgun key>'
|
||||
export MAILGUN_DOMAIN='<mailgun sender domain (e.g. mg.yourdomain.com)>'
|
||||
export DJANGO_AWS_ACCESS_KEY_ID=
|
||||
export DJANGO_AWS_SECRET_ACCESS_KEY=
|
||||
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_ALLOWED_HOSTS'] = '<as above>'
|
||||
os.environ['DJANGO_ADMIN_URL'] = '<as above>'
|
||||
os.environ['DJANGO_MAILGUN_API_KEY'] = '<as above>'
|
||||
os.environ['DJANGO_MAILGUN_SERVER_NAME'] = '<as above>'
|
||||
os.environ['MAILGUN_SENDER_DOMAIN'] = '<as above>'
|
||||
os.environ['MAILGUN_API_KEY'] = '<as above>'
|
||||
os.environ['MAILGUN_DOMAIN'] = '<as above>'
|
||||
os.environ['DJANGO_AWS_ACCESS_KEY_ID'] = ''
|
||||
os.environ['DJANGO_AWS_SECRET_ACCESS_KEY'] = ''
|
||||
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
|
||||
.. _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
|
||||
----------------------
|
||||
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
Deployment with Elastic Beanstalk
|
||||
==========================================
|
||||
|
||||
.. index:: Elastic Beanstalk
|
||||
|
||||
Warning: Experimental
|
||||
---------------------
|
||||
|
||||
This is experimental. For the time being there will be bugs and issues. If you've never used Elastic Beanstalk before, please hold off before trying this option.
|
||||
|
||||
On the other hand, we need help cleaning this up. If you do have knowledge of Elastic Beanstalk, we would appreciate the help. :)
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
* awsebcli
|
||||
|
||||
Instructions
|
||||
-------------
|
||||
|
||||
If you haven't done so, create a directory of environments::
|
||||
|
||||
eb init -p python3.4 MY_PROJECT_SLUG
|
||||
|
||||
Replace `MY_PROJECT_SLUG` with the value you entered for `project_slug`.
|
||||
|
||||
Once that is done, create the environment (server) where the app will run::
|
||||
|
||||
eb create MY_PROJECT_SLUG
|
||||
# Note: This will eventually fail on a postgres error, because postgres doesn't exist yet
|
||||
|
||||
Now make sure you are in the right environment::
|
||||
|
||||
eb list
|
||||
|
||||
If you are not in the right environment, then put yourself in the correct one::
|
||||
|
||||
eb use MY_PROJECT_SLUG
|
||||
|
||||
Set the environment variables. Notes: You will be prompted if the `.env` file is missing. The script will ignore any PostgreSQL values, as RDS uses it's own system::
|
||||
|
||||
# Set the environment variables
|
||||
python ebsetenv.py
|
||||
|
||||
Speaking of PostgreSQL, go to the Elasting Beanstalk configuration panel for RDS. Create new RDS database, with these attributes:
|
||||
|
||||
* PostgreSQL
|
||||
* Version 9.4.9
|
||||
* Size db.t2.micro (You can upgrade later)
|
||||
|
||||
(Get some coffee, this is going to take a while)
|
||||
|
||||
Once you have a database specified, deploy again so your instance can pick up the new PostgreSQL values::
|
||||
|
||||
eb deploy
|
||||
|
||||
Take a look::
|
||||
|
||||
eb open
|
||||
|
||||
FAQ
|
||||
-----
|
||||
|
||||
Why Not Use Docker on Elastic Beanstalk?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Because I didn't want to add an abstraction (Docker) on top of an abstraction (Elastic Beanstalk) on top of an abstraction (Cookiecutter Django).
|
||||
|
||||
Why Can't I Use Both Docker/Heroku with Elastic Beanstalk?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Because the environment variables that our Docker and Heroku setups use for PostgreSQL access is different then how Amazon RDS handles this access. At this time we're just trying to get things to work reliably with Elastic Beanstalk, and full integration will come later.
|
|
@ -25,7 +25,6 @@ Contents:
|
|||
faq
|
||||
troubleshooting
|
||||
my-favorite-cookie
|
||||
deployment-with-elastic-beanstalk
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
|
|
@ -1,69 +1,61 @@
|
|||
Project Generation Options
|
||||
==========================
|
||||
|
||||
project_name [project_name]:
|
||||
Your human-readable project name, including any capitalization or spaces.
|
||||
project_name [My Awesome Project]:
|
||||
Your project's human-readable name, capitals and spaces allowed.
|
||||
|
||||
project_slug [project_name]:
|
||||
The slug of your project, without dashes or spaces. Used to name your repo
|
||||
project_slug [my_awesome_project]:
|
||||
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
|
||||
is needed.
|
||||
|
||||
author_name [Your Name]:
|
||||
You! This goes into places like the LICENSE file.
|
||||
description [Behold My Awesome Project!]
|
||||
Describes your project and gets used in places like `README.rst` and such.
|
||||
|
||||
email [Your email]:
|
||||
Your email address.
|
||||
author_name [Daniel Roy Greenfeld]:
|
||||
This is you! The value goes into places like `LICENSE` and such.
|
||||
|
||||
description [A short description of the project.]
|
||||
Used in the generated README.rst and other places.
|
||||
email [daniel-roy-greenfeld@example.com]:
|
||||
The email address you want to identify yourself in the project.
|
||||
|
||||
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]
|
||||
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]
|
||||
Used in the base settings file for the `TIME_ZONE` value.
|
||||
|
||||
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.
|
||||
The value to be used for the `TIME_ZONE` setting of the project.
|
||||
|
||||
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]
|
||||
Whether to use Docker_, separating the app and database into separate
|
||||
containers.
|
||||
Indicates whether the project should be configured to use Docker_ and `Docker Compose`_.
|
||||
|
||||
use_heroku [n]
|
||||
Add configuration to deploy the application to a Heroku_ instance.
|
||||
postgresql_version [1]
|
||||
Select a PostgreSQL_ version to use. The choices are:
|
||||
|
||||
use_compressor [n]
|
||||
Use `Django Compressor`_ to minify and combine rendered JavaScript and CSS
|
||||
into cachable static resources.
|
||||
1. 10.3
|
||||
2. 10.2
|
||||
3. 10.1
|
||||
4. 9.6
|
||||
5. 9.5
|
||||
6. 9.4
|
||||
7. 9.3
|
||||
|
||||
js_task_runner [1]
|
||||
Select a JavaScript task runner. The choices are:
|
||||
|
@ -73,34 +65,63 @@ js_task_runner [1]
|
|||
3. None
|
||||
|
||||
custom_bootstrap_compilation [n]
|
||||
If you use Grunt, scaffold out recompiling Bootstrap as as task. (Useful for letting you change Bootstrap variables in real time.) Consult project README for more details.
|
||||
Indicates whether the project should support Bootstrap recompilation
|
||||
via the selected JavaScript task runner's task. This can be useful
|
||||
for real-time Bootstrap variable alteration.
|
||||
|
||||
open_source_license [1]
|
||||
Select a software license for the project. The choices are:
|
||||
use_compressor [n]
|
||||
Indicates whether the project should be configured to use `Django Compressor`_.
|
||||
|
||||
1. MIT_
|
||||
2. BSD_
|
||||
3. GPLv3_
|
||||
4. `Apache Software License 2.0`_
|
||||
5. Not open source
|
||||
use_celery [n]
|
||||
Indicates whether the project should be configured to use Celery_.
|
||||
|
||||
use_mailhog [n]
|
||||
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
|
||||
.. _BSD: https://opensource.org/licenses/BSD-3-Clause
|
||||
.. _GPLv3: https://www.gnu.org/licenses/gpl.html
|
||||
.. _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_CLIENT SENTRY_CLIENT n/a raven.contrib.django.raven_compat.DjangoClient
|
||||
DJANGO_SENTRY_LOG_LEVEL SENTRY_LOG_LEVEL n/a logging.INFO
|
||||
DJANGO_MAILGUN_API_KEY MAILGUN_ACCESS_KEY n/a raises error
|
||||
DJANGO_MAILGUN_SERVER_NAME MAILGUN_SERVER_NAME n/a raises error
|
||||
MAILGUN_SENDER_DOMAIN MAILGUN_SENDER_DOMAIN n/a raises error
|
||||
MAILGUN_API_KEY MAILGUN_ACCESS_KEY n/a raises error
|
||||
MAILGUN_DOMAIN MAILGUN_SENDER_DOMAIN 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
|
||||
DJANGO_OPBEAT_APP_ID OPBEAT['APP_ID'] n/a raises error
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
"""
|
||||
NOTE:
|
||||
the below code is to be maintained Python 2.x-compatible
|
||||
as the whole Cookiecutter Django project initialization
|
||||
can potentially be run in Python 2.x environment
|
||||
(at least so we presume in `pre_gen_project.py`).
|
||||
|
||||
TODO: ? restrict Cookiecutter Django project initialization to Python 3.x environments only
|
||||
"""
|
||||
|
||||
import os
|
||||
import random
|
||||
import shutil
|
||||
import string
|
||||
import sys
|
||||
|
||||
try:
|
||||
# Inspired by https://github.com/django/django/blob/master/django/utils/crypto.py
|
||||
# Inspired by
|
||||
# https://github.com/django/django/blob/master/django/utils/crypto.py
|
||||
random = random.SystemRandom()
|
||||
using_sysrandom = True
|
||||
except NotImplementedError:
|
||||
|
@ -13,28 +25,23 @@ except NotImplementedError:
|
|||
PROJECT_DIR_PATH = os.path.realpath(os.path.curdir)
|
||||
|
||||
|
||||
def remove_file(file_path: str) -> None:
|
||||
if os.path.exists(file_path):
|
||||
os.remove(file_path)
|
||||
|
||||
|
||||
def remove_open_source_project_only_files() -> None:
|
||||
filenames = [
|
||||
'CONTRIBUTORS.txt'
|
||||
def remove_open_source_project_only_files():
|
||||
file_names = [
|
||||
'CONTRIBUTORS.txt',
|
||||
]
|
||||
for filename in filenames:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, filename))
|
||||
for file_name in file_names:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
||||
|
||||
|
||||
def remove_gplv3_files() -> None:
|
||||
filenames = [
|
||||
'COPYING'
|
||||
def remove_gplv3_files():
|
||||
file_names = [
|
||||
'COPYING',
|
||||
]
|
||||
for filename in filenames:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, filename))
|
||||
for file_name in file_names:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
||||
|
||||
|
||||
def remove_pycharm_files() -> None:
|
||||
def remove_pycharm_files():
|
||||
idea_dir_path = os.path.join(PROJECT_DIR_PATH, '.idea')
|
||||
if os.path.exists(idea_dir_path):
|
||||
shutil.rmtree(idea_dir_path)
|
||||
|
@ -44,101 +51,78 @@ def remove_pycharm_files() -> None:
|
|||
shutil.rmtree(docs_dir_path)
|
||||
|
||||
|
||||
def remove_docker_files() -> None:
|
||||
def remove_docker_files():
|
||||
shutil.rmtree(os.path.join(PROJECT_DIR_PATH, 'compose'))
|
||||
|
||||
filenames = [
|
||||
file_names = [
|
||||
'local.yml',
|
||||
'production.yml',
|
||||
'.dockerignore'
|
||||
'.dockerignore',
|
||||
]
|
||||
for filename in filenames:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, filename))
|
||||
for file_name in file_names:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
||||
|
||||
|
||||
def remove_heroku_files() -> None:
|
||||
filenames = [
|
||||
def remove_heroku_files():
|
||||
file_names = [
|
||||
'Procfile',
|
||||
'runtime.txt'
|
||||
'runtime.txt',
|
||||
'requirements.txt',
|
||||
]
|
||||
for filename in filenames:
|
||||
remove_file(os.path.join(PROJECT_DIR_PATH, filename))
|
||||
for file_name in file_names:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
||||
|
||||
|
||||
def remove_elasticbeanstalk_files() -> None:
|
||||
ebextensions_dir_path = os.path.join(PROJECT_DIR_PATH, '.ebextensions')
|
||||
if os.path.exists(ebextensions_dir_path):
|
||||
shutil.rmtree(ebextensions_dir_path)
|
||||
def remove_dotenv_file():
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, '.env'))
|
||||
|
||||
filenames = [
|
||||
'ebsetenv.py'
|
||||
|
||||
def remove_grunt_files():
|
||||
file_names = [
|
||||
'Gruntfile.js',
|
||||
]
|
||||
for filename in filenames:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, filename))
|
||||
for file_name in file_names:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
||||
|
||||
|
||||
def try_remove_paas_files() -> None:
|
||||
none_paas_files_left = True
|
||||
|
||||
if '{{ cookiecutter.use_heroku }}'.lower() != 'y':
|
||||
remove_heroku_files()
|
||||
none_paas_files_left &= True
|
||||
else:
|
||||
none_paas_files_left &= False
|
||||
|
||||
if '{{ cookiecutter.use_elasticbeanstalk_experimental }}'.lower() != 'y':
|
||||
remove_elasticbeanstalk_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() -> None:
|
||||
filenames = [
|
||||
'Gruntfile.js'
|
||||
def remove_gulp_files():
|
||||
file_names = [
|
||||
'gulpfile.js',
|
||||
]
|
||||
for filename in filenames:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, filename))
|
||||
for file_name in file_names:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
||||
|
||||
|
||||
def remove_gulp_files() -> None:
|
||||
filenames = [
|
||||
'gulpfile.js'
|
||||
def remove_packagejson_file():
|
||||
file_names = [
|
||||
'package.json',
|
||||
]
|
||||
for filename in filenames:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, filename))
|
||||
for file_name in file_names:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, file_name))
|
||||
|
||||
|
||||
def remove_packagejson_file() -> None:
|
||||
filenames = [
|
||||
'package.json'
|
||||
]
|
||||
for filename in filenames:
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, filename))
|
||||
def remove_celery_app():
|
||||
shutil.rmtree(os.path.join(PROJECT_DIR_PATH, '{{ cookiecutter.project_slug }}', 'taskapp'))
|
||||
|
||||
|
||||
def remove_celery_app() -> None:
|
||||
task_app_path = os.path.join(PROJECT_DIR_PATH, '{{ cookiecutter.project_slug }}', 'taskapp')
|
||||
shutil.rmtree(task_app_path)
|
||||
def remove_dottravisyml_file():
|
||||
os.remove(os.path.join(PROJECT_DIR_PATH, '.travis.yml'))
|
||||
|
||||
|
||||
def append_to_gitignore(path) -> None:
|
||||
def append_to_project_gitignore(path):
|
||||
gitignore_file_path = os.path.join(PROJECT_DIR_PATH, '.gitignore')
|
||||
with open(gitignore_file_path, 'a') as gitignore_file:
|
||||
gitignore_file.write(path)
|
||||
gitignore_file.write(os.linesep)
|
||||
|
||||
|
||||
def generate_random_string(length: int,
|
||||
using_digits: bool = False,
|
||||
using_ascii_letters: bool = False,
|
||||
using_punctuation: bool = False) -> str:
|
||||
def generate_random_string(length,
|
||||
using_digits=False,
|
||||
using_ascii_letters=False,
|
||||
using_punctuation=False):
|
||||
"""
|
||||
Returns a securely generated random string.
|
||||
For instance, opting out for 50 symbol-long, [a-z][A-Z][0-9] string
|
||||
Example:
|
||||
opting out for 50 symbol-long, [a-z][A-Z][0-9] string
|
||||
would yield log_2((26+26+50)^50) ~= 334 bit strength.
|
||||
"""
|
||||
if not using_sysrandom:
|
||||
|
@ -154,61 +138,114 @@ def generate_random_string(length: int,
|
|||
.replace('"', '') \
|
||||
.replace("'", '') \
|
||||
.replace('\\', '')
|
||||
return ''.join([random.choice(symbols) for i in range(length)])
|
||||
return ''.join([random.choice(symbols) for _ in range(length)])
|
||||
|
||||
|
||||
def replace_flag_with_random_string(file_path: str,
|
||||
flag: str,
|
||||
def set_flag(file_path,
|
||||
flag,
|
||||
value=None,
|
||||
*args,
|
||||
**kwargs) -> None:
|
||||
**kwargs):
|
||||
if value is None:
|
||||
random_string = generate_random_string(*args, **kwargs)
|
||||
if random_string is None:
|
||||
print("We couldn't find a secure pseudo-random number generator on your system. "
|
||||
"Please, {} manually.".format(flag))
|
||||
import sys
|
||||
sys.stdout.write(
|
||||
"We couldn't find a secure pseudo-random number generator on your system. "
|
||||
"Please, make sure to manually {} later.".format(flag)
|
||||
)
|
||||
random_string = flag
|
||||
value = random_string
|
||||
|
||||
with open(file_path, 'r+') as file:
|
||||
file_contents = file.read().replace(flag, random_string)
|
||||
file.seek(0)
|
||||
file.write(file_contents)
|
||||
file.truncate()
|
||||
with open(file_path, 'r+') as f:
|
||||
file_contents = f.read().replace(flag, value)
|
||||
f.seek(0)
|
||||
f.write(file_contents)
|
||||
f.truncate()
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def set_django_secret_key(file_path: str) -> None:
|
||||
replace_flag_with_random_string(file_path, '!!!SET DJANGO_SECRET_KEY!!!',
|
||||
def set_django_secret_key(file_path):
|
||||
django_secret_key = set_flag(
|
||||
file_path,
|
||||
'!!!SET DJANGO_SECRET_KEY!!!',
|
||||
length=50,
|
||||
using_digits=True,
|
||||
using_ascii_letters=True,
|
||||
using_punctuation=True)
|
||||
using_ascii_letters=True
|
||||
)
|
||||
return django_secret_key
|
||||
|
||||
|
||||
def set_postgres_user(file_path: str) -> None:
|
||||
replace_flag_with_random_string(file_path, '!!!SET POSTGRES_USER!!!',
|
||||
def set_postgres_user(file_path,
|
||||
value=None):
|
||||
postgres_user = set_flag(
|
||||
file_path,
|
||||
'!!!SET POSTGRES_USER!!!',
|
||||
value=value,
|
||||
length=8,
|
||||
using_ascii_letters=True)
|
||||
using_ascii_letters=True
|
||||
)
|
||||
return postgres_user
|
||||
|
||||
|
||||
def set_postgres_password(file_path: str) -> None:
|
||||
replace_flag_with_random_string(file_path, '!!!SET POSTGRES_PASSWORD!!!',
|
||||
length=30,
|
||||
def set_postgres_password(file_path):
|
||||
postgres_password = set_flag(
|
||||
file_path,
|
||||
'!!!SET POSTGRES_PASSWORD!!!',
|
||||
length=42,
|
||||
using_digits=True,
|
||||
using_ascii_letters=True)
|
||||
using_ascii_letters=True
|
||||
)
|
||||
return postgres_password
|
||||
|
||||
|
||||
def initialize_dotenv(postgres_user):
|
||||
# Initializing `env.example` first.
|
||||
envexample_file_path = os.path.join(PROJECT_DIR_PATH, 'env.example')
|
||||
set_django_secret_key(envexample_file_path)
|
||||
set_postgres_user(envexample_file_path, value=postgres_user)
|
||||
set_postgres_password(envexample_file_path)
|
||||
# Renaming `env.example` to `.env`.
|
||||
dotenv_file_path = os.path.join(PROJECT_DIR_PATH, '.env')
|
||||
shutil.move(envexample_file_path, dotenv_file_path)
|
||||
|
||||
|
||||
def initialize_localyml(postgres_user):
|
||||
set_postgres_user(os.path.join(PROJECT_DIR_PATH, 'local.yml'), value=postgres_user)
|
||||
|
||||
|
||||
def initialize_local_settings():
|
||||
set_django_secret_key(os.path.join(PROJECT_DIR_PATH, 'config', 'settings', 'local.py'))
|
||||
|
||||
|
||||
def initialize_test_settings():
|
||||
set_django_secret_key(os.path.join(PROJECT_DIR_PATH, 'config', 'settings', 'test.py'))
|
||||
|
||||
|
||||
def main():
|
||||
postgres_user = generate_random_string(length=16, using_ascii_letters=True)
|
||||
initialize_dotenv(postgres_user)
|
||||
initialize_localyml(postgres_user)
|
||||
initialize_local_settings()
|
||||
initialize_test_settings()
|
||||
|
||||
if '{{ cookiecutter.open_source_license }}' == 'Not open source':
|
||||
remove_open_source_project_only_files()
|
||||
|
||||
if '{{ cookiecutter.open_source_license}}' != 'GPLv3':
|
||||
remove_gplv3_files()
|
||||
|
||||
if '{{ cookiecutter.use_pycharm }}'.lower() != 'y':
|
||||
if '{{ cookiecutter.use_pycharm }}'.lower() == 'n':
|
||||
remove_pycharm_files()
|
||||
|
||||
if '{{ cookiecutter.use_docker }}'.lower() != 'y':
|
||||
if '{{ cookiecutter.use_docker }}'.lower() == 'n':
|
||||
remove_docker_files()
|
||||
|
||||
try_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':
|
||||
remove_grunt_files()
|
||||
|
@ -221,31 +258,23 @@ def main():
|
|||
|
||||
if '{{ cookiecutter.js_task_runner }}'.lower() in ['grunt', 'gulp'] \
|
||||
and '{{ cookiecutter.use_docker }}'.lower() == 'y':
|
||||
print(
|
||||
"You selected to use docker and a JS task runner. "
|
||||
"This is NOT supported out of the box for now. "
|
||||
"You can continue to use the project like you normally would, "
|
||||
"but you would need to add a JS task runner service "
|
||||
"to your Docker Compose configuration manually."
|
||||
TERMINATOR = "\x1b[0m"
|
||||
INFO = "\x1b[1;33m [INFO]: "
|
||||
sys.stdout.write(
|
||||
INFO +
|
||||
"Docker and {} JS task runner ".format('{{ cookiecutter.js_task_runner }}'.lower().capitalize()) +
|
||||
"working together not supported yet. "
|
||||
"You can continue using the generated project like you normally would, "
|
||||
"however you would need to add a JS task runner service "
|
||||
"to your Docker Compose configuration manually." +
|
||||
TERMINATOR
|
||||
)
|
||||
|
||||
if '{{ cookiecutter.use_celery }}'.lower() == 'n':
|
||||
remove_celery_app()
|
||||
|
||||
append_to_gitignore('.envs/')
|
||||
append_to_gitignore('.env')
|
||||
|
||||
set_django_secret_key(os.path.join(PROJECT_DIR_PATH, 'config', 'settings', 'local.py'))
|
||||
set_django_secret_key(os.path.join(PROJECT_DIR_PATH, 'config', 'settings', 'test.py'))
|
||||
set_django_secret_key(os.path.join(PROJECT_DIR_PATH, '.envs', '.production', '.django'))
|
||||
|
||||
envs_local_postgres = os.path.join(PROJECT_DIR_PATH, '.envs', '.local', '.postgres')
|
||||
set_postgres_user(envs_local_postgres)
|
||||
set_postgres_password(envs_local_postgres)
|
||||
|
||||
envs_production_postgres = os.path.join(PROJECT_DIR_PATH, '.envs', '.production', '.postgres')
|
||||
set_postgres_user(envs_production_postgres)
|
||||
set_postgres_password(envs_production_postgres)
|
||||
if '{{ cookiecutter.use_travisci }}'.lower() == 'n':
|
||||
remove_dottravisyml_file()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -1,31 +1,62 @@
|
|||
"""
|
||||
NOTE:
|
||||
the below code is to be maintained Python 2.x-compatible
|
||||
as the whole Cookiecutter Django project initialization
|
||||
can potentially be run in Python 2.x environment.
|
||||
|
||||
TODO: ? restrict Cookiecutter Django project initialization to Python 3.x environments only
|
||||
"""
|
||||
|
||||
project_slug = '{{ cookiecutter.project_slug }}'
|
||||
|
||||
if hasattr(project_slug, 'isidentifier'):
|
||||
assert project_slug.isidentifier(), 'Project slug should be valid Python identifier!'
|
||||
assert project_slug.isidentifier(), "'{}' project slug is not a valid Python identifier.".format(project_slug)
|
||||
|
||||
elasticbeanstalk = '{{ cookiecutter.use_elasticbeanstalk_experimental }}'.lower()
|
||||
heroku = '{{ cookiecutter.use_heroku }}'.lower()
|
||||
docker = '{{ cookiecutter.use_docker }}'.lower()
|
||||
assert "\\" not in "{{ cookiecutter.author_name }}", "Don't include backslashes in author name."
|
||||
|
||||
if elasticbeanstalk == 'y' and (heroku == 'y' or docker == 'y'):
|
||||
raise Exception("Cookiecutter Django's EXPERIMENTAL Elastic Beanstalk support is incompatible with Heroku and Docker setups.")
|
||||
|
||||
if docker == 'n':
|
||||
using_docker = '{{ cookiecutter.use_docker }}'.lower()
|
||||
if using_docker == 'n':
|
||||
TERMINATOR = "\x1b[0m"
|
||||
WARNING = "\x1b[1;33m [WARNING]: "
|
||||
INFO = "\x1b[1;33m [INFO]: "
|
||||
HINT = "\x1b[3;33m"
|
||||
SUCCESS = "\x1b[1;32m [SUCCESS]: "
|
||||
|
||||
import sys
|
||||
|
||||
python_major_version = sys.version_info[0]
|
||||
|
||||
if python_major_version == 2:
|
||||
sys.stdout.write("WARNING: Cookiecutter Django does not support Python 2! Stability is guaranteed with Python 3.4+ only. Are you sure you want to proceed? (y/n)")
|
||||
|
||||
yes_options = set(['y'])
|
||||
no_options = set(['n', ''])
|
||||
sys.stdout.write(
|
||||
WARNING +
|
||||
"Cookiecutter Django does not support Python 2. "
|
||||
"Stability is guaranteed with Python 3.6+ only, "
|
||||
"are you sure you want to proceed (y/n)? " +
|
||||
TERMINATOR
|
||||
)
|
||||
yes_options, no_options = frozenset(['y']), frozenset(['n'])
|
||||
while True:
|
||||
choice = raw_input().lower()
|
||||
if choice in no_options:
|
||||
if choice in yes_options:
|
||||
break
|
||||
elif choice in no_options:
|
||||
sys.stdout.write(
|
||||
INFO +
|
||||
"Generation process stopped as requested." +
|
||||
TERMINATOR
|
||||
)
|
||||
sys.exit(1)
|
||||
elif choice in yes_options:
|
||||
pass
|
||||
else:
|
||||
sys.stdout.write("Please respond with %s or %s"
|
||||
% (', '.join([o for o in yes_options if not o == ''])
|
||||
, ', '.join([o for o in no_options if not o == ''])))
|
||||
sys.stdout.write(
|
||||
HINT +
|
||||
"Please respond with {} or {}: ".format(
|
||||
', '.join(["'{}'".format(o) for o in yes_options if not o == '']),
|
||||
', '.join(["'{}'".format(o) for o in no_options if not o == ''])
|
||||
) +
|
||||
TERMINATOR
|
||||
)
|
||||
|
||||
sys.stdout.write(
|
||||
SUCCESS +
|
||||
"Project initialized, keep up the good work!" +
|
||||
TERMINATOR
|
||||
)
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
cookiecutter==1.6.0
|
||||
flake8==3.5.0 # pyup: != 2.6.0
|
||||
sh==1.12.14
|
||||
binaryornot==0.4.4
|
||||
|
||||
# Testing
|
||||
pytest==3.2.5
|
||||
|
||||
# Code quality
|
||||
# ------------------------------------------------------------------------------
|
||||
flake8==3.5.0
|
||||
pycodestyle==2.3.1
|
||||
pyflakes==1.6.0
|
||||
|
||||
|
||||
# Testing
|
||||
# ------------------------------------------------------------------------------
|
||||
tox==2.9.1
|
||||
pytest==3.4.2
|
||||
pytest-cookies==0.3.0
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
# These requirements prevented an upgrade to Django 1.10.
|
||||
django-coverage-plugin==1.5.0
|
||||
django-autoslug==1.9.3
|
||||
|
8
setup.py
8
setup.py
|
@ -10,7 +10,7 @@ except ImportError:
|
|||
|
||||
# Our version ALWAYS matches the version of Django we support
|
||||
# If Django has a new release, we branch, tag, then update this setting after the tag.
|
||||
version = '1.10.7'
|
||||
version = '2.0.2'
|
||||
|
||||
if sys.argv[-1] == 'tag':
|
||||
os.system('git tag -a %s -m "version %s"' % (version, version))
|
||||
|
@ -34,16 +34,14 @@ setup(
|
|||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Environment :: Console',
|
||||
'Framework :: Django :: 1.10',
|
||||
'Framework :: Django :: 2.0',
|
||||
'Intended Audience :: Developers',
|
||||
'Natural Language :: English',
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: Implementation :: CPython',
|
||||
'Programming Language :: Python :: Implementation :: PyPy',
|
||||
'Topic :: Software Development',
|
||||
],
|
||||
keywords=(
|
||||
|
|
|
@ -12,10 +12,13 @@ cd .cache/docker
|
|||
|
||||
# create the project using the default settings in cookiecutter.json
|
||||
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
|
||||
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
|
||||
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
|
||||
|
|
5
tox.ini
5
tox.ini
|
@ -1,12 +1,11 @@
|
|||
[tox]
|
||||
skipsdist = true
|
||||
envlist = py34,py35
|
||||
envlist = py36
|
||||
|
||||
[testenv]
|
||||
passenv = LC_ALL, LANG, HOME
|
||||
deps =
|
||||
binaryornot
|
||||
flake8==2.5.5
|
||||
pytest-cookies
|
||||
sh
|
||||
commands = py.test {posargs:tests}
|
||||
commands = pytest {posargs:./tests}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
packages:
|
||||
yum:
|
||||
git: []
|
||||
postgresql94-devel: []
|
||||
libjpeg-turbo-devel: []
|
|
@ -1,46 +0,0 @@
|
|||
#This sample requires you to create a separate configuration file that defines the custom
|
||||
# option settings for CacheCluster properties.
|
||||
|
||||
Resources:
|
||||
MyCacheSecurityGroup:
|
||||
Type: "AWS::EC2::SecurityGroup"
|
||||
Properties:
|
||||
GroupDescription: "Lock cache down to webserver access only"
|
||||
SecurityGroupIngress :
|
||||
- IpProtocol : "tcp"
|
||||
FromPort :
|
||||
Fn::GetOptionSetting:
|
||||
OptionName : "CachePort"
|
||||
DefaultValue: "6379"
|
||||
ToPort :
|
||||
Fn::GetOptionSetting:
|
||||
OptionName : "CachePort"
|
||||
DefaultValue: "6379"
|
||||
SourceSecurityGroupName:
|
||||
Ref: "AWSEBSecurityGroup"
|
||||
MyElastiCache:
|
||||
Type: "AWS::ElastiCache::CacheCluster"
|
||||
Properties:
|
||||
CacheNodeType:
|
||||
Fn::GetOptionSetting:
|
||||
OptionName : "CacheNodeType"
|
||||
DefaultValue : "cache.t2.micro"
|
||||
NumCacheNodes:
|
||||
Fn::GetOptionSetting:
|
||||
OptionName : "NumCacheNodes"
|
||||
DefaultValue : "1"
|
||||
Engine:
|
||||
Fn::GetOptionSetting:
|
||||
OptionName : "Engine"
|
||||
DefaultValue : "redis"
|
||||
VpcSecurityGroupIds:
|
||||
-
|
||||
Fn::GetAtt:
|
||||
- MyCacheSecurityGroup
|
||||
- GroupId
|
||||
|
||||
Outputs:
|
||||
ElastiCache:
|
||||
Description : "ID of ElastiCache Cache Cluster with Redis Engine"
|
||||
Value :
|
||||
Ref : "MyElastiCache"
|
|
@ -1,6 +0,0 @@
|
|||
option_settings:
|
||||
"aws:elasticbeanstalk:customoption":
|
||||
CacheNodeType : cache.t2.micro
|
||||
NumCacheNodes : 1
|
||||
Engine : redis
|
||||
CachePort : 6379
|
|
@ -1,17 +0,0 @@
|
|||
container_commands:
|
||||
01_migrate:
|
||||
command: "source /opt/python/run/venv/bin/activate && python manage.py migrate --noinput"
|
||||
leader_only: True
|
||||
02_collectstatic:
|
||||
command: "source /opt/python/run/venv/bin/activate && python manage.py collectstatic --noinput"
|
||||
option_settings:
|
||||
"aws:elasticbeanstalk:application:environment":
|
||||
DJANGO_SETTINGS_MODULE: "config.settings.production"
|
||||
REDIS_ENDPOINT_ADDRESS: '`{ "Fn::GetAtt" : [ "MyElastiCache", "RedisEndpoint.Address"]}`'
|
||||
REDIS_PORT: '`{ "Fn::GetAtt" : [ "MyElastiCache", "RedisEndpoint.Port"]}`'
|
||||
"aws:elasticbeanstalk:container:python":
|
||||
WSGIPath: "config/wsgi.py"
|
||||
NumProcesses: 3
|
||||
NumThreads: 20
|
||||
"aws:elasticbeanstalk:container:python:staticfiles":
|
||||
"/static/": "www/static/"
|
|
@ -1,3 +0,0 @@
|
|||
container_commands:
|
||||
01_setup_apache:
|
||||
command: "cp .ebextensions/enable_mod_deflate.conf /etc/httpd/conf.d/enable_mod_deflate.conf"
|
|
@ -1,25 +0,0 @@
|
|||
# mod_deflate configuration
|
||||
<IfModule mod_deflate.c>
|
||||
# Restrict compression to these MIME types
|
||||
AddOutputFilterByType DEFLATE text/plain
|
||||
AddOutputFilterByType DEFLATE text/html
|
||||
AddOutputFilterByType DEFLATE application/xhtml+xml
|
||||
AddOutputFilterByType DEFLATE text/xml
|
||||
AddOutputFilterByType DEFLATE application/xml
|
||||
AddOutputFilterByType DEFLATE application/xml+rss
|
||||
AddOutputFilterByType DEFLATE application/x-javascript
|
||||
AddOutputFilterByType DEFLATE text/javascript
|
||||
AddOutputFilterByType DEFLATE text/css
|
||||
# Level of compression (Highest 9 - Lowest 1)
|
||||
DeflateCompressionLevel 9
|
||||
# Netscape 4.x has some problems.
|
||||
BrowserMatch ^Mozilla/4 gzip-only-text/html
|
||||
# Netscape 4.06-4.08 have some more problems
|
||||
BrowserMatch ^Mozilla/4\.0[678] no-gzip
|
||||
# MSIE masquerades as Netscape, but it is fine
|
||||
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html
|
||||
<IfModule mod_headers.c>
|
||||
# Make sure proxies don't deliver the wrong content
|
||||
Header append Vary User-Agent env=!dont-vary
|
||||
</IfModule>
|
||||
</IfModule>
|
|
@ -6,7 +6,7 @@
|
|||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.local" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="docker-compose://[$PROJECT_DIR$/local.yml]:pycharm/python" />
|
||||
<option name="SDK_HOME" value="docker-compose://[$PROJECT_DIR$/local.yml]:django/python" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="false" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.test" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="docker-compose://[$PROJECT_DIR$/local.yml]:pycharm/python" />
|
||||
<option name="SDK_HOME" value="docker-compose://[$PROJECT_DIR$/local.yml]:django/python" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.test" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="docker-compose://[$PROJECT_DIR$/local.yml]:pycharm/python" />
|
||||
<option name="SDK_HOME" value="docker-compose://[$PROJECT_DIR$/local.yml]:django/python" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.test" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="docker-compose://[$PROJECT_DIR$/local.yml]:pycharm/python" />
|
||||
<option name="SDK_HOME" value="docker-compose://[$PROJECT_DIR$/local.yml]:django/python" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.test" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="docker-compose://[$PROJECT_DIR$/local.yml]:pycharm/python" />
|
||||
<option name="SDK_HOME" value="docker-compose://[$PROJECT_DIR$/local.yml]:django/python" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.test" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="docker-compose://[$PROJECT_DIR$/local.yml]:pycharm/python" />
|
||||
<option name="SDK_HOME" value="docker-compose://[$PROJECT_DIR$/local.yml]:django/python" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
|
|
|
@ -8,4 +8,4 @@ before_install:
|
|||
- sudo apt-get install -qq libsqlite3-dev libxml2 libxml2-dev libssl-dev libbz2-dev wget curl llvm
|
||||
language: python
|
||||
python:
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
|
|
|
@ -61,7 +61,7 @@ module.exports = function (grunt) {
|
|||
options: {
|
||||
outputStyle: 'nested',
|
||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
includePaths: ['bower_components/bootstrap-sass/assets/stylesheets/bootstrap/'],
|
||||
includePaths: ['node_modules/bootstrap/scss'],
|
||||
{% endif %}
|
||||
sourceMap: false,
|
||||
precision: 10
|
||||
|
@ -74,7 +74,7 @@ module.exports = function (grunt) {
|
|||
options: {
|
||||
outputStyle: 'compressed',
|
||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
includePaths: ['bower_components/bootstrap-sass/assets/stylesheets/bootstrap/'],
|
||||
includePaths: ['node_modules/bootstrap/scss'],
|
||||
{% endif %}
|
||||
sourceMap: false,
|
||||
precision: 10
|
||||
|
|
|
@ -79,8 +79,6 @@ Email Server
|
|||
{% if cookiecutter.use_docker == 'y' %}
|
||||
In development, it is often nice to be able to see emails that are being sent from your application. For that reason local SMTP server `MailHog`_ with a web interface is available as docker container.
|
||||
|
||||
.. _mailhog: https://github.com/mailhog/MailHog
|
||||
|
||||
Container mailhog will start automatically when you will run all docker containers.
|
||||
Please check `cookiecutter-django Docker documentation`_ for more details how to start all containers.
|
||||
|
||||
|
@ -88,8 +86,6 @@ With MailHog running, to view messages that are sent by your application, open y
|
|||
{% else %}
|
||||
In development, it is often nice to be able to see emails that are being sent from your application. If you choose to use `MailHog`_ when generating the project a local SMTP server with a web interface will be available.
|
||||
|
||||
.. _mailhog: https://github.com/mailhog/MailHog
|
||||
|
||||
To start the service, make sure you have nodejs installed, and then type the following::
|
||||
|
||||
$ npm install
|
||||
|
@ -101,6 +97,7 @@ To view messages that are sent by your application, open your browser and go to
|
|||
|
||||
The email server will exit when you exit the Grunt task on the CLI with Ctrl+C.
|
||||
{% endif %}
|
||||
.. _mailhog: https://github.com/mailhog/MailHog
|
||||
{% endif %}
|
||||
{% if cookiecutter.use_sentry_for_error_reporting == "y" %}
|
||||
|
||||
|
@ -135,22 +132,21 @@ See detailed `cookiecutter-django Docker documentation`_.
|
|||
|
||||
.. _`cookiecutter-django Docker documentation`: http://cookiecutter-django.readthedocs.io/en/latest/deployment-with-docker.html
|
||||
{% endif %}
|
||||
{% if cookiecutter.use_elasticbeanstalk_experimental.lower() == 'y' %}
|
||||
|
||||
Elastic Beanstalk
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
See detailed `cookiecutter-django Elastic Beanstalk documentation`_.
|
||||
|
||||
.. _`cookiecutter-django Docker documentation`: http://cookiecutter-django.readthedocs.io/en/latest/deployment-with-elastic-beanstalk.html
|
||||
|
||||
{% endif %}
|
||||
{% if cookiecutter.custom_bootstrap_compilation == "y" %}
|
||||
Custom Bootstrap Compilation
|
||||
^^^^^^
|
||||
|
||||
To get automatic Bootstrap recompilation with variables of your choice, install bootstrap sass (`bower install bootstrap-sass`) and tweak your variables in `static/sass/custom_bootstrap_vars`.
|
||||
The generated CSS is set up with automatic Bootstrap recompilation with variables of your choice.
|
||||
Bootstrap v4 is installed using npm and customised by tweaking your variables in ``static/sass/custom_bootstrap_vars``.
|
||||
|
||||
(You can find a list of available variables [in the bootstrap-sass source](https://github.com/twbs/bootstrap-sass/blob/master/assets/stylesheets/bootstrap/_variables.scss), or get explanations on them in the [Bootstrap docs](https://getbootstrap.com/customize/).)
|
||||
You can find a list of available variables `in the bootstrap source`_, or get explanations on them in the `Bootstrap docs`_.
|
||||
|
||||
{% if cookiecutter.js_task_runner == 'Gulp' %}
|
||||
Bootstrap's javascript as well as its dependencies is concatenated into a single file: ``static/js/vendors.js``.
|
||||
{% endif %}
|
||||
|
||||
.. _in the bootstrap source: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_variables.scss
|
||||
.. _Bootstrap docs: https://getbootstrap.com/docs/4.0/getting-started/theming/
|
||||
|
||||
{% endif %}
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
FROM python:3.5
|
||||
FROM python:3.6-alpine
|
||||
|
||||
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
|
||||
COPY ./requirements /requirements
|
||||
RUN pip install -r /requirements/local.txt
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
FROM python:3.5
|
||||
FROM python:3.6-alpine
|
||||
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
|
||||
RUN groupadd -r django \
|
||||
&& useradd -r -g django django
|
||||
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
|
||||
|
||||
RUN addgroup -S django \
|
||||
&& adduser -S -G django django
|
||||
|
||||
# Requirements have to be pulled and installed here, otherwise caching won't work
|
||||
COPY ./requirements /requirements
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
@ -25,7 +25,7 @@ export DATABASE_URL=postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres:5432/$
|
|||
export CELERY_BROKER_URL=$REDIS_URL/0
|
||||
{% endif %}
|
||||
|
||||
function postgres_ready(){
|
||||
postgres_ready() {
|
||||
python << END
|
||||
import sys
|
||||
import psycopg2
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
@ -6,4 +6,4 @@ set -o nounset
|
|||
|
||||
|
||||
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.
|
||||
|
||||
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/
|
||||
Base settings to build other settings files upon.
|
||||
"""
|
||||
|
||||
import environ
|
||||
|
||||
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 }}')
|
||||
|
||||
# Load operating system environment variables and then prepare to use them
|
||||
env = environ.Env()
|
||||
|
||||
# .env file, should load only in development environment
|
||||
READ_DOT_ENV_FILE = env.bool('DJANGO_READ_DOT_ENV_FILE', default=False)
|
||||
|
||||
if READ_DOT_ENV_FILE:
|
||||
# Operating System Environment variables have precedence over variables defined in the .env file,
|
||||
# that is to say variables from the .env files will only be used if not defined
|
||||
# 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')
|
||||
# OS environment variables take precedence over variables from .env
|
||||
env.read_env(str(ROOT_DIR.path('.env')))
|
||||
|
||||
# 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 = [
|
||||
# Default Django apps:
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
|
||||
# Useful template tags:
|
||||
# 'django.contrib.humanize',
|
||||
|
||||
# Admin
|
||||
# 'django.contrib.humanize', # Handy template tags
|
||||
'django.contrib.admin',
|
||||
]
|
||||
THIRD_PARTY_APPS = [
|
||||
'crispy_forms', # Form layouts
|
||||
'allauth', # registration
|
||||
'allauth.account', # registration
|
||||
'allauth.socialaccount', # registration
|
||||
]
|
||||
'crispy_forms',
|
||||
|
||||
# Apps specific for this project go here.
|
||||
'allauth',
|
||||
'allauth.account',
|
||||
'allauth.socialaccount',
|
||||
]
|
||||
LOCAL_APPS = [
|
||||
# custom users app
|
||||
'{{ cookiecutter.project_slug }}.users.apps.UsersConfig',
|
||||
# Your stuff: custom apps go here
|
||||
]
|
||||
|
||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
|
||||
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
|
||||
|
||||
# MIDDLEWARE CONFIGURATION
|
||||
# ------------------------------------------------------------------------------
|
||||
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
|
||||
# MIGRATIONS
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#migration-modules
|
||||
MIGRATION_MODULES = {
|
||||
'sites': '{{ cookiecutter.project_slug }}.contrib.sites.migrations'
|
||||
}
|
||||
|
||||
# DEBUG
|
||||
# AUTHENTICATION
|
||||
# ------------------------------------------------------------------------------
|
||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug
|
||||
DEBUG = env.bool('DJANGO_DEBUG', False)
|
||||
|
||||
# FIXTURE CONFIGURATION
|
||||
# ------------------------------------------------------------------------------
|
||||
# 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/#authentication-backends
|
||||
AUTHENTICATION_BACKENDS = [
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
'allauth.account.auth_backends.AuthenticationBackend',
|
||||
]
|
||||
# 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
|
||||
MANAGERS = ADMINS
|
||||
|
||||
# DATABASE CONFIGURATION
|
||||
# PASSWORDS
|
||||
# ------------------------------------------------------------------------------
|
||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases
|
||||
# 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
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#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.PBKDF2PasswordHasher',
|
||||
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
|
||||
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
|
||||
'django.contrib.auth.hashers.BCryptPasswordHasher',
|
||||
]
|
||||
|
||||
# PASSWORD VALIDATION
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
|
@ -242,50 +129,142 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||
},
|
||||
]
|
||||
|
||||
# AUTHENTICATION CONFIGURATION
|
||||
# MIDDLEWARE
|
||||
# ------------------------------------------------------------------------------
|
||||
AUTHENTICATION_BACKENDS = [
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
'allauth.account.auth_backends.AuthenticationBackend',
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#middleware
|
||||
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',
|
||||
]
|
||||
|
||||
# Some really nice defaults
|
||||
ACCOUNT_AUTHENTICATION_METHOD = 'username'
|
||||
ACCOUNT_EMAIL_REQUIRED = True
|
||||
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
|
||||
# STATIC
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#static-root
|
||||
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)
|
||||
ACCOUNT_ADAPTER = '{{cookiecutter.project_slug}}.users.adapters.AccountAdapter'
|
||||
SOCIALACCOUNT_ADAPTER = '{{cookiecutter.project_slug}}.users.adapters.SocialAccountAdapter'
|
||||
# MEDIA
|
||||
# ------------------------------------------------------------------------------
|
||||
# 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
|
||||
# Select the correct user model
|
||||
AUTH_USER_MODEL = 'users.User'
|
||||
LOGIN_REDIRECT_URL = 'users:redirect'
|
||||
LOGIN_URL = 'account_login'
|
||||
# TEMPLATES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#templates
|
||||
TEMPLATES = [
|
||||
{
|
||||
# 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
|
||||
AUTOSLUG_SLUGIFY_FUNCTION = 'slugify.slugify'
|
||||
{% if cookiecutter.use_celery == 'y' %}
|
||||
########## CELERY
|
||||
# FIXTURES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#fixture-dirs
|
||||
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']
|
||||
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-broker_url
|
||||
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://':
|
||||
CELERY_RESULT_BACKEND = 'redis://'
|
||||
else:
|
||||
CELERY_RESULT_BACKEND = CELERY_BROKER_URL
|
||||
########## END CELERY
|
||||
{% endif %}
|
||||
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-accept_content
|
||||
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
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://django-compressor.readthedocs.io/en/latest/quickstart/#installation
|
||||
INSTALLED_APPS += ['compressor']
|
||||
STATICFILES_FINDERS += ['compressor.finders.CompressorFinder']
|
||||
|
||||
{%- endif %}
|
||||
|
||||
# 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
|
||||
# Your stuff...
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -1,47 +1,20 @@
|
|||
"""
|
||||
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
|
||||
|
||||
# DEBUG
|
||||
# GENERAL
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
|
||||
DEBUG = env.bool('DJANGO_DEBUG', default=True)
|
||||
TEMPLATES[0]['OPTIONS']['debug'] = DEBUG
|
||||
|
||||
# SECRET CONFIGURATION
|
||||
# ------------------------------------------------------------------------------
|
||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
||||
# Note: This key only used for development and testing.
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#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
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
# CACHES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#caches
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
|
@ -49,40 +22,62 @@ CACHES = {
|
|||
}
|
||||
}
|
||||
|
||||
# TEMPLATES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#templates
|
||||
TEMPLATES[0]['OPTIONS']['debug'] = DEBUG
|
||||
|
||||
# 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
|
||||
# ------------------------------------------------------------------------------
|
||||
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware', ]
|
||||
INSTALLED_APPS += ['debug_toolbar', ]
|
||||
|
||||
INTERNAL_IPS = ['127.0.0.1', '10.0.2.2', ]
|
||||
{% if cookiecutter.use_docker == 'y' %}
|
||||
{# [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':
|
||||
ip = socket.gethostbyname(socket.gethostname())
|
||||
INTERNAL_IPS += [ip[:-1] + '1']
|
||||
{% endif %}
|
||||
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#prerequisites
|
||||
INSTALLED_APPS += ['debug_toolbar']
|
||||
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#middleware
|
||||
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']
|
||||
# https://django-debug-toolbar.readthedocs.io/en/latest/configuration.html#debug-toolbar-config
|
||||
DEBUG_TOOLBAR_CONFIG = {
|
||||
'DISABLE_PANELS': [
|
||||
'debug_toolbar.panels.redirects.RedirectsPanel',
|
||||
],
|
||||
'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':
|
||||
ip = socket.gethostbyname(socket.gethostname())
|
||||
INTERNAL_IPS += [ip[:-1] + '1']
|
||||
{%- endif %}
|
||||
|
||||
# django-extensions
|
||||
# ------------------------------------------------------------------------------
|
||||
INSTALLED_APPS += ['django_extensions', ]
|
||||
# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration
|
||||
INSTALLED_APPS += ['django_extensions']
|
||||
{% if cookiecutter.use_celery == 'y' -%}
|
||||
|
||||
# TESTING
|
||||
# Celery
|
||||
# ------------------------------------------------------------------------------
|
||||
TEST_RUNNER = 'django.test.runner.DiscoverRunner'
|
||||
{% if cookiecutter.use_celery == 'y' %}
|
||||
########## CELERY
|
||||
# In development, all tasks will be executed locally by blocking until the task returns
|
||||
# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-task_always_eager
|
||||
CELERY_ALWAYS_EAGER = True
|
||||
########## END CELERY
|
||||
{% endif %}
|
||||
# Your local stuff: Below this line define 3rd party library settings
|
||||
|
||||
{%- endif %}
|
||||
# Your stuff...
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -1,222 +1,189 @@
|
|||
"""
|
||||
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
|
||||
{% endif %}
|
||||
|
||||
from .base import * # noqa
|
||||
|
||||
# SECRET CONFIGURATION
|
||||
# GENERAL
|
||||
# ------------------------------------------------------------------------------
|
||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
||||
# Raises ImproperlyConfigured exception if DJANGO_SECRET_KEY not in os.environ
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
||||
SECRET_KEY = env('DJANGO_SECRET_KEY')
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
||||
ALLOWED_HOSTS = env.list('DJANGO_ALLOWED_HOSTS', default=['{{ cookiecutter.domain_name }}'])
|
||||
|
||||
|
||||
# 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
|
||||
# DATABASES
|
||||
# ------------------------------------------------------------------------------
|
||||
# See https://docs.djangoproject.com/en/dev/ref/middleware/#module-django.middleware.security
|
||||
# and https://docs.djangoproject.com/en/dev/howto/deployment/checklist/#run-manage-py-check-deploy
|
||||
|
||||
# set this to 60 seconds and then to 518400 when you can prove it works
|
||||
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_HEADERS = {
|
||||
'Cache-Control': 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') # 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
|
||||
# ------------------------------------------------------------------------------
|
||||
{% if cookiecutter.use_elasticbeanstalk_experimental.lower() == 'y' -%}
|
||||
# Uses Amazon RDS for database hosting, which doesn't follow the Heroku-style spec
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
'NAME': env('RDS_DB_NAME'),
|
||||
'USER': env('RDS_USERNAME'),
|
||||
'PASSWORD': env('RDS_PASSWORD'),
|
||||
'HOST': env('RDS_HOSTNAME'),
|
||||
'PORT': env('RDS_PORT'),
|
||||
'CONN_MAX_AGE': env.int('CONN_MAX_AGE', default={{ _DEFAULT_CONN_MAX_AGE }}),
|
||||
}
|
||||
}
|
||||
{% else %}
|
||||
# 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 }})
|
||||
{%- endif %}
|
||||
DATABASES['default']['ATOMIC_REQUESTS'] = True
|
||||
DATABASES['default']['CONN_MAX_AGE'] = env.int('CONN_MAX_AGE', default=60)
|
||||
|
||||
# CACHING
|
||||
# CACHES
|
||||
# ------------------------------------------------------------------------------
|
||||
{% if cookiecutter.use_elasticbeanstalk_experimental.lower() == 'y' -%}
|
||||
REDIS_LOCATION = 'redis://{}:{}/0'.format(
|
||||
env('REDIS_ENDPOINT_ADDRESS'),
|
||||
env('REDIS_PORT')
|
||||
)
|
||||
{% else %}
|
||||
REDIS_LOCATION = '{0}/{1}'.format(env('REDIS_URL', default='redis://127.0.0.1:6379'), 0)
|
||||
{%- endif %}
|
||||
# Heroku URL does not pass the DB number, so we parse it in
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django_redis.cache.RedisCache',
|
||||
'LOCATION': REDIS_LOCATION,
|
||||
'LOCATION': "{}/0".format(env('REDIS_URL', default='redis://127.0.0.1:6379')),
|
||||
'OPTIONS': {
|
||||
'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
|
||||
'IGNORE_EXCEPTIONS': True,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
||||
# Sentry Configuration
|
||||
# SECURITY
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header
|
||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#secure-ssl-redirect
|
||||
SECURE_SSL_REDIRECT = env.bool('DJANGO_SECURE_SSL_REDIRECT', default=True)
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-secure
|
||||
SESSION_COOKIE_SECURE = True
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#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']
|
||||
# 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': 'max-age=%d, s-maxage=%d, must-revalidate' % (_AWS_EXPIRY, _AWS_EXPIRY),
|
||||
}
|
||||
|
||||
# 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 = 'https://s3.amazonaws.com/%s/' % 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 = 'https://s3.amazonaws.com/%s/media/' % AWS_STORAGE_BUCKET_NAME
|
||||
{%- endif %}
|
||||
|
||||
# TEMPLATES
|
||||
# ------------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#templates
|
||||
TEMPLATES[0]['OPTIONS']['loaders'] = [
|
||||
(
|
||||
'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']
|
||||
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']
|
||||
|
||||
{% if cookiecutter.use_whitenoise == 'y' -%}
|
||||
# WhiteNoise
|
||||
# ------------------------------------------------------------------------------
|
||||
# http://whitenoise.evans.io/en/latest/django.html#enable-whitenoise
|
||||
MIDDLEWARE = ['whitenoise.middleware.WhiteNoiseMiddleware'] + MIDDLEWARE
|
||||
|
||||
{%- 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
|
||||
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']
|
||||
MIDDLEWARE = ['raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware'] + MIDDLEWARE
|
||||
|
||||
# Sentry
|
||||
# ------------------------------------------------------------------------------
|
||||
SENTRY_DSN = env('DJANGO_SENTRY_DSN')
|
||||
SENTRY_CLIENT = env('DJANGO_SENTRY_CLIENT', default='raven.contrib.django.raven_compat.DjangoClient')
|
||||
LOGGING = {
|
||||
|
@ -224,7 +191,7 @@ LOGGING = {
|
|||
'disable_existing_loggers': True,
|
||||
'root': {
|
||||
'level': 'WARNING',
|
||||
'handlers': ['sentry', ],
|
||||
'handlers': ['sentry'],
|
||||
},
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
|
@ -246,38 +213,39 @@ LOGGING = {
|
|||
'loggers': {
|
||||
'django.db.backends': {
|
||||
'level': 'ERROR',
|
||||
'handlers': ['console', ],
|
||||
'handlers': ['console'],
|
||||
'propagate': False,
|
||||
},
|
||||
'raven': {
|
||||
'level': 'DEBUG',
|
||||
'handlers': ['console', ],
|
||||
'handlers': ['console'],
|
||||
'propagate': False,
|
||||
},
|
||||
'sentry.errors': {
|
||||
'level': 'DEBUG',
|
||||
'handlers': ['console', ],
|
||||
'handlers': ['console'],
|
||||
'propagate': False,
|
||||
},
|
||||
'django.security.DisallowedHost': {
|
||||
'level': 'ERROR',
|
||||
'handlers': ['console', 'sentry', ],
|
||||
'handlers': ['console', 'sentry'],
|
||||
'propagate': False,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
SENTRY_CELERY_LOGLEVEL = env.int('DJANGO_SENTRY_LOG_LEVEL', logging.INFO)
|
||||
RAVEN_CONFIG = {
|
||||
'CELERY_LOGLEVEL': env.int('DJANGO_SENTRY_LOG_LEVEL', logging.INFO),
|
||||
'DSN': SENTRY_DSN
|
||||
}
|
||||
{% elif cookiecutter.use_sentry_for_error_reporting == 'n' %}
|
||||
# LOGGING CONFIGURATION
|
||||
{%- else %}
|
||||
# LOGGING
|
||||
# ------------------------------------------------------------------------------
|
||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#logging
|
||||
# A sample logging configuration. The only tangible logging
|
||||
# performed by this configuration is to send an email to
|
||||
# the site admins on every HTTP 500 error when DEBUG=False.
|
||||
# the site admins bon every HTTP 500 error when DEBUG=False.
|
||||
# See https://docs.djangoproject.com/en/dev/topics/logging for
|
||||
# more details on how to customize your logging configuration.
|
||||
LOGGING = {
|
||||
|
@ -297,7 +265,7 @@ LOGGING = {
|
|||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false', ],
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler'
|
||||
},
|
||||
'console': {
|
||||
|
@ -308,20 +276,33 @@ LOGGING = {
|
|||
},
|
||||
'loggers': {
|
||||
'django.request': {
|
||||
'handlers': ['mail_admins', ],
|
||||
'handlers': ['mail_admins'],
|
||||
'level': 'ERROR',
|
||||
'propagate': True
|
||||
},
|
||||
'django.security.DisallowedHost': {
|
||||
'level': 'ERROR',
|
||||
'handlers': ['console', 'mail_admins', ],
|
||||
'handlers': ['console', 'mail_admins'],
|
||||
'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']
|
||||
# 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,21 @@
|
|||
"""
|
||||
Test settings for {{cookiecutter.project_name}} project.
|
||||
|
||||
- Used to run tests fast on the continuous integration server and locally
|
||||
With these settings, tests run faster.
|
||||
"""
|
||||
|
||||
from .base import * # noqa
|
||||
|
||||
|
||||
# DEBUG
|
||||
# GENERAL
|
||||
# ------------------------------------------------------------------------------
|
||||
# Turn debug off so tests run faster
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#debug
|
||||
DEBUG = False
|
||||
TEMPLATES[0]['OPTIONS']['debug'] = False
|
||||
|
||||
# SECRET CONFIGURATION
|
||||
# ------------------------------------------------------------------------------
|
||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
|
||||
# Note: This key only used for development and testing.
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#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'
|
||||
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
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#caches
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
|
@ -38,24 +23,35 @@ CACHES = {
|
|||
}
|
||||
}
|
||||
|
||||
# TESTING
|
||||
# PASSWORDS
|
||||
# ------------------------------------------------------------------------------
|
||||
TEST_RUNNER = 'django.test.runner.DiscoverRunner'
|
||||
|
||||
|
||||
# PASSWORD HASHING
|
||||
# ------------------------------------------------------------------------------
|
||||
# Use fast password hasher so tests run faster
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers
|
||||
PASSWORD_HASHERS = [
|
||||
'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']['debug'] = DEBUG
|
||||
TEMPLATES[0]['OPTIONS']['loaders'] = [
|
||||
['django.template.loaders.cached.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...
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -20,7 +20,8 @@ from django.core.wsgi import get_wsgi_application
|
|||
|
||||
# This allows easy placement of apps within the interior
|
||||
# {{ cookiecutter.project_slug }} directory.
|
||||
app_path = os.path.dirname(os.path.abspath(__file__)).replace('/config', '')
|
||||
app_path = os.path.abspath(os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), os.pardir))
|
||||
sys.path.append(os.path.join(app_path, '{{ cookiecutter.project_slug }}'))
|
||||
|
||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
||||
|
|
|
@ -58,7 +58,7 @@ The `Docker compose documentation`_ explains in detail what you can accomplish i
|
|||
build: database
|
||||
webapp:
|
||||
build: webapp:
|
||||
command: /usr/bin/python3.4 manage.py runserver 0.0.0.0:8000 # dev setting
|
||||
command: /usr/bin/python3.6 manage.py runserver 0.0.0.0:8000 # dev setting
|
||||
# command: gunicorn -b 0.0.0.0:8000 wsgi:application # production setting
|
||||
volumes:
|
||||
- webapp/your_project_name:/path/to/container/workdir/
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
"""Converts a .env file to Elastic Beanstalk environment variables"""
|
||||
|
||||
import os
|
||||
from sys import exit
|
||||
from subprocess import check_call
|
||||
|
||||
try:
|
||||
import dotenv
|
||||
except ImportError:
|
||||
print("Please install the 'dotenv' library: 'pip install dotenv'")
|
||||
exit()
|
||||
|
||||
def main():
|
||||
if not os.path.exists('.env'):
|
||||
print('ERROR!! .env file is missing!')
|
||||
print("Please copy 'env.example' to '.env' and add appropriate values")
|
||||
exit()
|
||||
command = ['eb', 'setenv']
|
||||
failures = []
|
||||
for key, value in dotenv.Dotenv('.env').items():
|
||||
if key.startswith('POSTGRES'):
|
||||
print('Skipping POSTGRES values - Amazon RDS provides these')
|
||||
continue
|
||||
if value:
|
||||
command.append("{}={}".format(key, value))
|
||||
else:
|
||||
failures.append(key)
|
||||
if failures:
|
||||
for failure in failures:
|
||||
print("{} requires a value".format(failure))
|
||||
else:
|
||||
print(' '.join(command))
|
||||
check_call(command)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -10,6 +10,9 @@ var gulp = require('gulp'),
|
|||
sass = require('gulp-sass'),
|
||||
autoprefixer = require('gulp-autoprefixer'),
|
||||
cssnano = require('gulp-cssnano'),
|
||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
concat = require('gulp-concat'),
|
||||
{% endif %}
|
||||
rename = require('gulp-rename'),
|
||||
del = require('del'),
|
||||
plumber = require('gulp-plumber'),
|
||||
|
@ -25,15 +28,24 @@ var gulp = require('gulp'),
|
|||
// Relative paths function
|
||||
var pathsConfig = function (appName) {
|
||||
this.app = "./" + (appName || pjson.name);
|
||||
var vendorsRoot = 'node_modules/';
|
||||
|
||||
return {
|
||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
bootstrapSass: vendorsRoot + '/bootstrap/scss',
|
||||
vendorsJs: [
|
||||
vendorsRoot + 'jquery/dist/jquery.slim.js',
|
||||
vendorsRoot + 'popper.js/dist/umd/popper.js',
|
||||
vendorsRoot + 'bootstrap/dist/js/bootstrap.js'
|
||||
],
|
||||
{% endif %}
|
||||
app: this.app,
|
||||
templates: this.app + '/templates',
|
||||
css: this.app + '/static/css',
|
||||
sass: this.app + '/static/sass',
|
||||
fonts: this.app + '/static/fonts',
|
||||
images: this.app + '/static/images',
|
||||
js: this.app + '/static/js',
|
||||
js: this.app + '/static/js'
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -45,8 +57,15 @@ var paths = pathsConfig();
|
|||
|
||||
// Styles autoprefixing and minification
|
||||
gulp.task('styles', function() {
|
||||
return gulp.src(paths.sass + '/*.scss')
|
||||
.pipe(sass().on('error', sass.logError))
|
||||
return gulp.src(paths.sass + '/project.scss')
|
||||
.pipe(sass({
|
||||
includePaths: [
|
||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
paths.bootstrapSass,
|
||||
{% endif %}
|
||||
paths.sass
|
||||
]
|
||||
}).on('error', sass.logError))
|
||||
.pipe(plumber()) // Checks for errors
|
||||
.pipe(autoprefixer({browsers: ['last 2 versions']})) // Adds vendor prefixes
|
||||
.pipe(pixrem()) // add fallbacks for rem units
|
||||
|
@ -65,6 +84,20 @@ gulp.task('scripts', function() {
|
|||
.pipe(gulp.dest(paths.js));
|
||||
});
|
||||
|
||||
|
||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
// Vendor Javascript minification
|
||||
gulp.task('vendor-scripts', function() {
|
||||
return gulp.src(paths.vendorsJs)
|
||||
.pipe(concat('vendors.js'))
|
||||
.pipe(gulp.dest(paths.js))
|
||||
.pipe(plumber()) // Checks for errors
|
||||
.pipe(uglify()) // Minifies the js
|
||||
.pipe(rename({ suffix: '.min' }))
|
||||
.pipe(gulp.dest(paths.js));
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
// Image compression
|
||||
gulp.task('imgCompression', function(){
|
||||
return gulp.src(paths.images + '/*')
|
||||
|
@ -101,5 +134,5 @@ gulp.task('watch', function() {
|
|||
|
||||
// Default task
|
||||
gulp.task('default', function() {
|
||||
runSequence(['styles', 'scripts', 'imgCompression'], ['runServer', 'browserSync', 'watch']);
|
||||
runSequence(['styles', 'scripts', {% if cookiecutter.custom_bootstrap_compilation == 'y' %}'vendor-scripts', {% endif %}'imgCompression'], ['runServer', 'browserSync', 'watch']);
|
||||
});
|
||||
|
|
|
@ -41,7 +41,6 @@ services:
|
|||
image: redis:3.0
|
||||
|
||||
celeryworker:
|
||||
# https://github.com/docker/compose/issues/3220
|
||||
<<: *django
|
||||
depends_on:
|
||||
- redis
|
||||
|
@ -51,7 +50,6 @@ services:
|
|||
command: /start-celeryworker.sh
|
||||
|
||||
celerybeat:
|
||||
# https://github.com/docker/compose/issues/3220
|
||||
<<: *django
|
||||
depends_on:
|
||||
- redis
|
||||
|
|
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
|
|
@ -5,6 +5,9 @@
|
|||
"devDependencies": {
|
||||
{% if cookiecutter.js_task_runner == 'Grunt' %}
|
||||
"autoprefixer-core": "~5.2.1",
|
||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
"bootstrap": "^4.0.0",
|
||||
{% endif %}
|
||||
"connect-livereload": "~0.3.2",
|
||||
"cssnano": "~2.1.0",
|
||||
"grunt": "~0.4.5",
|
||||
|
@ -12,14 +15,26 @@
|
|||
"grunt-contrib-watch": "~0.6.1",
|
||||
"grunt-postcss": "~0.5.5",
|
||||
"grunt-sass": "~1.0.0",
|
||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
"jquery": "^3.2.1-slim",
|
||||
{% endif %}
|
||||
"load-grunt-tasks": "~3.2.0",
|
||||
"pixrem": "~1.3.1",
|
||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
"popper.js": "^1.12.3",
|
||||
{% endif %}
|
||||
"time-grunt": "~1.2.1"
|
||||
{% elif cookiecutter.js_task_runner == 'Gulp' %}
|
||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
"bootstrap": "^4.0.0",
|
||||
{% endif %}
|
||||
"browser-sync": "^2.14.0",
|
||||
"del": "^2.2.2",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-autoprefixer": "^3.1.1",
|
||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
"gulp-concat": "^2.6.1",
|
||||
{% endif %}
|
||||
"gulp-cssnano": "^2.1.2",
|
||||
"gulp-imagemin": "^3.0.3",
|
||||
"gulp-pixrem": "^1.0.0",
|
||||
|
@ -28,6 +43,10 @@
|
|||
"gulp-sass": "^2.3.2",
|
||||
"gulp-uglify": "^2.0.0",
|
||||
"gulp-util": "^3.0.7",
|
||||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
"jquery": "^3.2.1-slim",
|
||||
"popper.js": "^1.12.3",
|
||||
{% endif %}
|
||||
"run-sequence": "^1.2.2"
|
||||
{% endif %}
|
||||
},
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
[pytest]
|
||||
DJANGO_SETTINGS_MODULE=config.settings.test
|
||||
{% if cookiecutter.js_task_runner != 'None' %}
|
||||
norecursedirs = node_modules
|
||||
{% endif %}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# This file is here because many Platforms as a Service look for
|
||||
# requirements.txt in the root directory of a project.
|
||||
# This file is expected by Heroku.
|
||||
|
||||
-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
|
||||
|
||||
|
||||
# Bleeding edge Django
|
||||
django==1.10.8 # pyup: >=1.10,<1.11
|
||||
# Conservative Django
|
||||
django==2.0.2 # pyup: < 2.1
|
||||
|
||||
# Configuration
|
||||
django-environ==0.4.4
|
||||
|
@ -16,41 +9,41 @@ whitenoise==3.3.1
|
|||
|
||||
|
||||
# Forms
|
||||
django-crispy-forms==1.7.0
|
||||
django-crispy-forms==1.7.1
|
||||
|
||||
# Models
|
||||
django-model-utils==3.0.0
|
||||
django-model-utils==3.1.1
|
||||
|
||||
# Images
|
||||
Pillow==4.3.0
|
||||
Pillow==5.0.0
|
||||
|
||||
# Password storage
|
||||
argon2-cffi==16.3.0
|
||||
argon2-cffi==18.1.0
|
||||
|
||||
# For user registration, either via email or social
|
||||
# Well-built with regular release cycles!
|
||||
django-allauth==0.34.0
|
||||
django-allauth==0.35.0
|
||||
|
||||
{% if cookiecutter.windows == 'y' -%}
|
||||
# On Windows, you must download/install psycopg2 manually
|
||||
# from http://www.lfd.uci.edu/~gohlke/pythonlibs/#psycopg
|
||||
{% else %}
|
||||
# Python-PostgreSQL Database Adapter
|
||||
psycopg2==2.7.3.2
|
||||
psycopg2==2.7.4 --no-binary psycopg2
|
||||
{%- endif %}
|
||||
|
||||
# Unicode slugification
|
||||
awesome-slugify==1.6.5
|
||||
|
||||
# Time zones support
|
||||
pytz==2017.3
|
||||
pytz==2018.3
|
||||
|
||||
# Redis support
|
||||
django-redis==4.8.0
|
||||
django-redis==4.9.0
|
||||
redis>=2.10.5
|
||||
|
||||
{% if cookiecutter.use_celery == "y" %}
|
||||
celery==3.1.25
|
||||
celery==3.1.25 # pyup: <4.0
|
||||
{% endif %}
|
||||
|
||||
{% if cookiecutter.use_compressor == "y" %}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
# Local development dependencies go here
|
||||
-r base.txt
|
||||
|
||||
coverage==4.4.2
|
||||
coverage==4.5.1
|
||||
django-coverage-plugin==1.5.0
|
||||
|
||||
Sphinx==1.6.5
|
||||
django-extensions==1.9.7
|
||||
Werkzeug==0.12.2
|
||||
django-test-plus==1.0.20
|
||||
factory-boy==2.9.2
|
||||
Sphinx==1.7.1
|
||||
django-extensions==2.0.0
|
||||
Werkzeug==0.14.1
|
||||
django-test-plus==1.0.22
|
||||
factory-boy==2.10.0
|
||||
|
||||
django-debug-toolbar==1.9.1
|
||||
|
||||
# improved REPL
|
||||
ipdb==0.10.3
|
||||
ipdb==0.11
|
||||
|
||||
pytest-django==3.1.2
|
||||
pytest-sugar==0.9.0
|
||||
pytest-sugar==0.9.1
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# Python-PostgreSQL Database Adapter
|
||||
# Assuming Windows is used locally, and *nix -- in production.
|
||||
# ------------------------------------------------------------
|
||||
psycopg2==2.7.3.2
|
||||
psycopg2==2.7.4 --no-binary psycopg2
|
||||
{%- endif %}
|
||||
|
||||
# WSGI Handler
|
||||
|
@ -16,24 +16,24 @@ gunicorn==19.7.1
|
|||
|
||||
# Static and Media Storage
|
||||
# ------------------------------------------------
|
||||
boto3==1.4.7
|
||||
boto3==1.6.2 # pyup: update minor
|
||||
django-storages==1.6.5
|
||||
{% if cookiecutter.use_whitenoise != 'y' -%}
|
||||
Collectfast==0.5.2
|
||||
Collectfast==0.6.0
|
||||
{%- endif %}
|
||||
|
||||
# Email backends for Mailgun, Postmark, SendGrid and more
|
||||
# -------------------------------------------------------
|
||||
django-anymail==1.2
|
||||
django-anymail==1.4
|
||||
|
||||
{% if cookiecutter.use_sentry_for_error_reporting == "y" -%}
|
||||
# Raven is the Sentry client
|
||||
# --------------------------
|
||||
raven==6.3.0
|
||||
raven==6.6.0
|
||||
{%- endif %}
|
||||
|
||||
{% if cookiecutter.use_opbeat == "y" -%}
|
||||
# Opbeat agent for performance monitoring
|
||||
# -----------------------------------------
|
||||
opbeat==3.5.3
|
||||
opbeat==3.6.1
|
||||
{%- endif %}
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
{% if cookiecutter.windows == 'y' -%}
|
||||
# Python-PostgreSQL Database Adapter
|
||||
# If using Win for dev, this assumes Unix in test/prod
|
||||
psycopg2==2.7.3.2
|
||||
psycopg2==2.7.4
|
||||
{%- endif %}
|
||||
|
||||
coverage==4.4.2
|
||||
coverage==4.5.1
|
||||
flake8==3.5.0 # pyup: != 2.6.0
|
||||
django-test-plus==1.0.20
|
||||
factory-boy==2.9.2
|
||||
django-test-plus==1.0.22
|
||||
factory-boy==2.10.0
|
||||
django-coverage-plugin==1.5.0
|
||||
|
||||
# pytest
|
||||
pytest-django==3.1.2
|
||||
pytest-sugar==0.9.0
|
||||
pytest-sugar==0.9.1
|
||||
|
|
|
@ -1 +1 @@
|
|||
python-3.6.2
|
||||
python-3.6.4
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
##basic build dependencies of various Django apps for Debian Jessie 9.x
|
||||
#build-essential metapackage install: make, gcc, g++,
|
||||
build-essential
|
||||
#required to translate
|
||||
gettext
|
||||
python3-dev
|
||||
|
||||
##shared dependencies of:
|
||||
##Pillow, pylibmc
|
||||
zlib1g-dev
|
||||
|
||||
##Postgresql and psycopg2 dependencies
|
||||
libpq-dev
|
||||
|
||||
##Pillow dependencies
|
||||
libtiff5-dev
|
||||
libjpeg62-turbo-dev
|
||||
libfreetype6-dev
|
||||
liblcms2-dev
|
||||
libwebp-dev
|
||||
|
||||
##django-extensions
|
||||
graphviz-dev
|
|
@ -11,11 +11,3 @@
|
|||
background-color: #f2dede;
|
||||
border-color: #eed3d7;
|
||||
}
|
||||
|
||||
/* Display django-debug-toolbar.
|
||||
See https://github.com/django-debug-toolbar/django-debug-toolbar/issues/742
|
||||
and https://github.com/pydanny/cookiecutter-django/issues/317
|
||||
*/
|
||||
[hidden][style="display: block;"] {
|
||||
display: block !important;
|
||||
}
|
||||
|
|
|
@ -1,54 +1,6 @@
|
|||
{% if cookiecutter.custom_bootstrap_compilation == 'y' %}
|
||||
@import "variables";
|
||||
@import "custom_bootstrap_vars";
|
||||
@import "mixins";
|
||||
|
||||
// Reset and dependencies
|
||||
@import "normalize";
|
||||
@import "print";
|
||||
@import "glyphicons";
|
||||
|
||||
// Core CSS
|
||||
@import "scaffolding";
|
||||
@import "type";
|
||||
@import "code";
|
||||
@import "grid";
|
||||
@import "tables";
|
||||
@import "forms";
|
||||
@import "buttons";
|
||||
|
||||
// Components
|
||||
@import "component-animations";
|
||||
@import "dropdowns";
|
||||
@import "button-groups";
|
||||
@import "input-groups";
|
||||
@import "navs";
|
||||
@import "navbar";
|
||||
@import "breadcrumbs";
|
||||
@import "pagination";
|
||||
@import "pager";
|
||||
@import "labels";
|
||||
@import "badges";
|
||||
@import "jumbotron";
|
||||
@import "thumbnails";
|
||||
@import "alerts";
|
||||
@import "progress-bars";
|
||||
@import "media";
|
||||
@import "list-group";
|
||||
@import "panels";
|
||||
@import "responsive-embed";
|
||||
@import "wells";
|
||||
@import "close";
|
||||
|
||||
// Components w/ JavaScript
|
||||
@import "modals";
|
||||
@import "tooltip";
|
||||
@import "popovers";
|
||||
@import "carousel";
|
||||
|
||||
// Utility classes
|
||||
@import "utilities";
|
||||
@import "responsive-utilities";
|
||||
@import "bootstrap";
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
@ -86,15 +38,3 @@ $red: #b94a48;
|
|||
border-color: $dark-pink;
|
||||
color: $red;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//Django Toolbar//
|
||||
////////////////////////////////
|
||||
|
||||
// Display django-debug-toolbar.
|
||||
// See https://github.com/django-debug-toolbar/django-debug-toolbar/issues/742
|
||||
// and https://github.com/pydanny/cookiecutter-django/issues/317
|
||||
|
||||
[hidden][style="display: block;"] {
|
||||
display: block !important;
|
||||
}
|
||||
|
|
|
@ -14,13 +14,19 @@
|
|||
<![endif]-->
|
||||
|
||||
{% block css %}
|
||||
{% endraw %}{% if cookiecutter.custom_bootstrap_compilation == "n" %}{% raw %}
|
||||
<!-- Latest compiled and minified Bootstrap 4 beta CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
|
||||
{% endraw %}{% endif %}{% raw %}
|
||||
|
||||
<!-- Your stuff: Third-party CSS libraries go here -->
|
||||
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress css %}{% endraw %}{% endif %}{% raw %}
|
||||
<!-- This file stores project-specific CSS -->
|
||||
{% endraw %}{% if cookiecutter.js_task_runner == "Gulp" and cookiecutter.use_compressor == "n" %}{% raw %}
|
||||
<link href="{% static 'css/project.min.css' %}" rel="stylesheet">
|
||||
{% endraw %}{% else %}{% raw %}
|
||||
<link href="{% static 'css/project.css' %}" rel="stylesheet">
|
||||
{% endraw %}{% endif %}{% raw %}
|
||||
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% endcompress %}{% endraw %}{% endif %}{% raw %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -88,12 +94,19 @@
|
|||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
{% block javascript %}
|
||||
{% endraw %}{% if cookiecutter.custom_bootstrap_compilation == "y" and cookiecutter.js_task_runner == "Gulp" %}{% raw %}
|
||||
<!-- Vendor dependencies bundled as one file-->
|
||||
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress js %}{% endraw %}{% endif %}{% raw %}
|
||||
<script src="{% static 'js/vendors.js' %}"></script>
|
||||
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% endcompress %}{% endraw %}{% endif %}{% raw %}
|
||||
{% endraw %}{% else %}{% raw %}
|
||||
<!-- Required by Bootstrap v4 beta -->
|
||||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
|
||||
|
||||
<!-- Your stuff: Third-party javascript libraries go here -->
|
||||
{% endraw %}{% endif %}{% raw %}
|
||||
|
||||
<!-- place project specific Javascript in this file -->
|
||||
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress js %}{% endraw %}{% endif %}{% raw %}
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
{% raw %}
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
{% if field|is_checkbox %}
|
||||
<div class="form-group{% if using_grid_layout %} row{% endif %}">
|
||||
{% if label_class %}
|
||||
<div class="controls col-{{ bootstrap_device_type }}-offset-{{ label_size }} {{ field_class }}">
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<{% if tag %}{{ tag }}{% else %}div{% endif %} id="div_{{ field.auto_id }}" {% if not field|is_checkbox %}class="form-group{% if using_grid_layout %} row{% endif %}{% else %}class="checkbox{% endif %}{% if wrapper_class %} {{ wrapper_class }}{% endif %}{% if form_show_errors%}{% if field.errors %} has-danger{% endif %}{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
|
||||
{% if field.label and not field|is_checkbox and form_show_labels %}
|
||||
<label for="{{ field.id_for_label }}" class="form-control-label {{ label_class }}{% if field.field.required %} requiredField{% endif %}">
|
||||
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
{% if field|is_checkboxselectmultiple %}
|
||||
{% include 'bootstrap4/layout/checkboxselectmultiple.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if field|is_radioselect %}
|
||||
{% include 'bootstrap4/layout/radioselect.html' %}
|
||||
{% endif %}
|
||||
|
||||
{% if not field|is_checkboxselectmultiple and not field|is_radioselect %}
|
||||
{% if field|is_checkbox and form_show_labels %}
|
||||
<label for="{{ field.id_for_label }}" class="{% if field.field.required %} requiredField{% endif %}">
|
||||
{% crispy_field field %}
|
||||
{{ field.label|safe }}
|
||||
{% include 'bootstrap4/layout/help_text_and_errors.html' %}
|
||||
</label>
|
||||
{% else %}
|
||||
<div class="{{ field_class }}">
|
||||
{% crispy_field field %}
|
||||
</div>
|
||||
{% include 'bootstrap4/layout/help_text_and_errors.html' %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</{% if tag %}{{ tag }}{% else %}div{% endif %}>
|
||||
{% if field|is_checkbox %}
|
||||
{% if label_class %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endraw %}
|
|
@ -1,7 +0,0 @@
|
|||
{% raw %}
|
||||
{% if form_show_errors and field.errors %}
|
||||
{% for error in field.errors %}
|
||||
<p id="error_{{ forloop.counter }}_{{ field.auto_id }}" class="text-danger help-block">{{ error }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endraw %}
|
|
@ -22,7 +22,7 @@ class Migration(migrations.Migration):
|
|||
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
||||
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
|
||||
('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
|
||||
('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')),
|
||||
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
|
||||
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
|
||||
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
from django.contrib.auth.models import AbstractUser
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class User(AbstractUser):
|
||||
|
||||
# First Name and Last Name do not cover name patterns
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from django.core.urlresolvers import reverse, resolve
|
||||
from django.urls import reverse, resolve
|
||||
|
||||
from test_plus.test import TestCase
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ from django.conf.urls import url
|
|||
|
||||
from . import views
|
||||
|
||||
app_name = 'users'
|
||||
urlpatterns = [
|
||||
url(
|
||||
regex=r'^$',
|
||||
|
@ -13,14 +14,14 @@ urlpatterns = [
|
|||
view=views.UserRedirectView.as_view(),
|
||||
name='redirect'
|
||||
),
|
||||
url(
|
||||
regex=r'^(?P<username>[\w.@+-]+)/$',
|
||||
view=views.UserDetailView.as_view(),
|
||||
name='detail'
|
||||
),
|
||||
url(
|
||||
regex=r'^~update/$',
|
||||
view=views.UserUpdateView.as_view(),
|
||||
name='update'
|
||||
),
|
||||
url(
|
||||
regex=r'^(?P<username>[\w.@+-]+)/$',
|
||||
view=views.UserDetailView.as_view(),
|
||||
name='detail'
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.views.generic import DetailView, ListView, RedirectView, UpdateView
|
||||
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.urls import reverse
|
||||
from django.views.generic import DetailView, ListView, RedirectView, UpdateView
|
||||
|
||||
from .models import User
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user