mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-08-06 13:10:17 +03:00
commit
638134bfa0
|
@ -10,7 +10,6 @@ language: python
|
||||||
python: 3.5
|
python: 3.5
|
||||||
|
|
||||||
env:
|
env:
|
||||||
- TOX_ENV=py27
|
|
||||||
- TOX_ENV=py34
|
- TOX_ENV=py34
|
||||||
- TOX_ENV=py35
|
- TOX_ENV=py35
|
||||||
|
|
||||||
|
|
32
CHANGELOG.md
32
CHANGELOG.md
|
@ -2,6 +2,38 @@
|
||||||
All enhancements and patches to Cookiecutter Django will be documented in this file.
|
All enhancements and patches to Cookiecutter Django will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [2015-10-08]
|
||||||
|
### Changed
|
||||||
|
- Elastic Beanstalk: Added --noinput to migrate command (@MightySCollins )
|
||||||
|
|
||||||
|
## [2015-10-07]
|
||||||
|
### Added
|
||||||
|
- Finished first pass at Elastic Beanstalk docs (@pydanny & @audreyr)
|
||||||
|
### Deleted
|
||||||
|
- Removed Heroku instant deploy button (@pydanny)
|
||||||
|
|
||||||
|
|
||||||
|
##[2016-09-29]
|
||||||
|
### Added
|
||||||
|
- Added default `AUTH_PASSWORD_VALIDATORS` configuration, generated by django 1.10 startproject. See [Password Validation docs](https://docs.djangoproject.com/en/1.10/topics/auth/passwords/#module-django.contrib.auth.password_validation") (@luzfcb)
|
||||||
|
- Rename `MIDDLEWARE_CLASSES` to `MIDDLEWARE` to enable support to [new style middleware](https://github.com/django/deps/blob/master/final/0005-improved-middleware.rst) introduced in Django 1.10 (@luzfcb)
|
||||||
|
- New setting `MAILGUN_SENDER_DOMAIN` to allow sending mail from any domain other than those registered with mailgun (@jangeador)
|
||||||
|
- add `urlpatterns` configuration to django-debug-toolbar, because the automatic configuration of `urlpatterns` was removed from django-debug-toolbar (@luzfcb)
|
||||||
|
- Added Temporary workaround on `requirements/local.txt` to fix django-debug-toolbar issue: https://github.com/pydanny/cookiecutter-django/issues/827 (@luzfcb)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Upgrade to Django 1.10.1 (@luzfcb)
|
||||||
|
- Upgrade django-model-utils to 2.6, django-redis to 4.5.0, redis to 2.10.5, Sphinx to 1.4.6, pytest-django to 3.0.0, django-anymail to 0.5, raven to 5.27.1, whitenoise to 3.2.2 (@luzfcb)
|
||||||
|
- Upgrade to Bootstrap 4 Alpha 4, jQuery to 3.1.1, tether.js to 1.3.7 (@luzfcb)
|
||||||
|
- Update `manage.py` to use same code of `manage.py` from Django 1.10 (@luzfcb)
|
||||||
|
- Sync `sites` app migrations with django 1.10, and fix aditional migrations to `sites` and `user` app (@luzfcb)
|
||||||
|
d changed 'admin' url on `config/urls.py`, to stay the same as generated by django 1.10 (@luzfcb)
|
||||||
|
- Make test_docker.sh tests pass by passing new password auth rules (@ssteinerx)
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- Removed django-autoslug because not support django 1.10 at this date (@luzfcb)
|
||||||
|
|
||||||
|
|
||||||
##[2016-09-10]
|
##[2016-09-10]
|
||||||
### Changed
|
### Changed
|
||||||
- Use app registry instead of INSTALLED_APPS to discover celery tasks (@dhepper)
|
- Use app registry instead of INSTALLED_APPS to discover celery tasks (@dhepper)
|
||||||
|
|
|
@ -39,9 +39,9 @@ To run all tests using various versions of python in virtualenvs defined in tox.
|
||||||
It is possible to tests with some versions of python, to do this the command
|
It is possible to tests with some versions of python, to do this the command
|
||||||
is::
|
is::
|
||||||
|
|
||||||
$ tox -e py27,py34
|
$ tox -e py34,py35
|
||||||
|
|
||||||
Will run py.test with the python2.7, and python3.4 interpreters, for
|
Will run py.test with the python3.4, and python3.5 interpreters, for
|
||||||
example.
|
example.
|
||||||
|
|
||||||
To run a particular test with tox for against your current Python version::
|
To run a particular test with tox for against your current Python version::
|
||||||
|
|
|
@ -16,6 +16,7 @@ Fábio C. Barrionuevo da Luz `@luzfcb`_ @luzfcb
|
||||||
Saurabh Kumar `@theskumar`_ @_theskumar
|
Saurabh Kumar `@theskumar`_ @_theskumar
|
||||||
Jannis Gebauer `@jayfk`_
|
Jannis Gebauer `@jayfk`_
|
||||||
Burhan Khalid `@burhan`_ @burhan
|
Burhan Khalid `@burhan`_ @burhan
|
||||||
|
Shupeyko Nikita `@webyneter`_ @webyneter
|
||||||
=========================== ============= ===========
|
=========================== ============= ===========
|
||||||
|
|
||||||
*Audrey is also the creator of Cookiecutter. Audrey and
|
*Audrey is also the creator of Cookiecutter. Audrey and
|
||||||
|
@ -26,6 +27,7 @@ Daniel are on the Cookiecutter core team.*
|
||||||
.. _@theskumar: https://github.com/theskumar
|
.. _@theskumar: https://github.com/theskumar
|
||||||
.. _@audreyr: https://github.com/audreyr
|
.. _@audreyr: https://github.com/audreyr
|
||||||
.. _@jayfk: https://github.com/jayfk
|
.. _@jayfk: https://github.com/jayfk
|
||||||
|
.. _@webyneter: https://github.com/webyneter
|
||||||
|
|
||||||
Other Contributors
|
Other Contributors
|
||||||
------------------
|
------------------
|
||||||
|
@ -58,6 +60,7 @@ Listed in alphabetical order.
|
||||||
Benjamin Abel
|
Benjamin Abel
|
||||||
Bo Lopker `@blopker`_
|
Bo Lopker `@blopker`_
|
||||||
Bouke Haarsma
|
Bouke Haarsma
|
||||||
|
Brent Payne `@brentpayne`_ @brentpayne
|
||||||
Burhan Khalid `@burhan`_ @burhan
|
Burhan Khalid `@burhan`_ @burhan
|
||||||
Catherine Devlin `@catherinedevlin`_
|
Catherine Devlin `@catherinedevlin`_
|
||||||
Cédric Gaspoz `@cgaspoz`_
|
Cédric Gaspoz `@cgaspoz`_
|
||||||
|
@ -88,6 +91,7 @@ Listed in alphabetical order.
|
||||||
Ian Lee `@IanLee1521`_
|
Ian Lee `@IanLee1521`_
|
||||||
Jan Van Bruggen `@jvanbrug`_
|
Jan Van Bruggen `@jvanbrug`_
|
||||||
Jens Nilsson `@phiberjenz`_
|
Jens Nilsson `@phiberjenz`_
|
||||||
|
Jimmy Gitonga `@afrowave`_ @afrowave
|
||||||
Julien Almarcha `@sladinji`_
|
Julien Almarcha `@sladinji`_
|
||||||
Julio Castillo `@juliocc`_
|
Julio Castillo `@juliocc`_
|
||||||
Kaido Kert `@kaidokert`_
|
Kaido Kert `@kaidokert`_
|
||||||
|
@ -95,6 +99,7 @@ Listed in alphabetical order.
|
||||||
Kaveh `@ka7eh`_
|
Kaveh `@ka7eh`_
|
||||||
Kevin A. Stone
|
Kevin A. Stone
|
||||||
Kevin Ndung'u `@kevgathuku`_
|
Kevin Ndung'u `@kevgathuku`_
|
||||||
|
Keith Webber `@townie`_
|
||||||
Krzysztof Szumny `@noisy`_
|
Krzysztof Szumny `@noisy`_
|
||||||
Krzysztof Żuraw `@krzysztofzuraw`_
|
Krzysztof Żuraw `@krzysztofzuraw`_
|
||||||
Leonardo Jimenez `@xpostudio4`_
|
Leonardo Jimenez `@xpostudio4`_
|
||||||
|
@ -104,33 +109,41 @@ Listed in alphabetical order.
|
||||||
Lyla Fischer
|
Lyla Fischer
|
||||||
Martin Blech
|
Martin Blech
|
||||||
Mathijs Hoogland `@MathijsHoogland`_
|
Mathijs Hoogland `@MathijsHoogland`_
|
||||||
|
Matt Braymer-Hayes `@mattayes`_ @mattayes
|
||||||
Matt Linares
|
Matt Linares
|
||||||
Matt Menzenski `@menzenski`_
|
Matt Menzenski `@menzenski`_
|
||||||
Matt Warren `@mfwarren`_
|
Matt Warren `@mfwarren`_
|
||||||
Matthew Sisley `@mjsisley`_
|
Matthew Sisley `@mjsisley`_
|
||||||
Meghan Heintz `@dot2dotseurat`_
|
Meghan Heintz `@dot2dotseurat`_
|
||||||
|
Mesut Yılmaz `@myilmaz`_
|
||||||
|
Michael Gecht `@mimischi`_ @_mischi
|
||||||
mozillazg `@mozillazg`_
|
mozillazg `@mozillazg`_
|
||||||
Pablo `@oubiga`_
|
Pablo `@oubiga`_
|
||||||
Parbhat Puri `@parbhat`_
|
Parbhat Puri `@parbhat`_
|
||||||
Peter Bittner `@bittner`_
|
Peter Bittner `@bittner`_
|
||||||
Raphael Pierzina `@hackebrot`_
|
Raphael Pierzina `@hackebrot`_
|
||||||
Raony Guimarães Corrêa `@raonyguimaraes`_
|
Raony Guimarães Corrêa `@raonyguimaraes`_
|
||||||
|
René Muhl `@rm--`_
|
||||||
Roman Afanaskin `@siauPatrick`_
|
Roman Afanaskin `@siauPatrick`_
|
||||||
Roman Osipenko `@romanosipenko`_
|
Roman Osipenko `@romanosipenko`_
|
||||||
Russell Davies
|
Russell Davies
|
||||||
stepmr `@stepmr`_
|
Sam Collins `@MightySCollins`_
|
||||||
|
Shupeyko Nikita `@webyneter`_
|
||||||
Sławek Ehlert `@slafs`_
|
Sławek Ehlert `@slafs`_
|
||||||
Srinivas Nyayapati `@shireenrao`_
|
Srinivas Nyayapati `@shireenrao`_
|
||||||
|
stepmr `@stepmr`_
|
||||||
Steve Steiner `@ssteinerX`_
|
Steve Steiner `@ssteinerX`_
|
||||||
Sule Marshall `@suledev`_
|
Sule Marshall `@suledev`_
|
||||||
Taylor Baldwin
|
Taylor Baldwin
|
||||||
Théo Segonds `@show0k`_
|
Théo Segonds `@show0k`_
|
||||||
|
Tim Freund `@timfreund`_
|
||||||
Tom Atkins `@knitatoms`_
|
Tom Atkins `@knitatoms`_
|
||||||
Tom Offermann
|
Tom Offermann
|
||||||
Travis McNeill `@Travistock`_ @tavistock_esq
|
Travis McNeill `@Travistock`_ @tavistock_esq
|
||||||
Vitaly Babiy
|
Vitaly Babiy
|
||||||
Vivian Guillen `@viviangb`_
|
Vivian Guillen `@viviangb`_
|
||||||
Will Farley `@goldhand`_ @g01dhand
|
Will Farley `@goldhand`_ @g01dhand
|
||||||
|
William Archinal `@archinal`_
|
||||||
Yaroslav Halchenko
|
Yaroslav Halchenko
|
||||||
========================== ============================ ==============
|
========================== ============================ ==============
|
||||||
|
|
||||||
|
@ -142,6 +155,7 @@ Listed in alphabetical order.
|
||||||
.. _@amjith: https://github.com/amjith
|
.. _@amjith: https://github.com/amjith
|
||||||
.. _@andor-pierdelacabeza: https://github.com/andor-pierdelacabeza
|
.. _@andor-pierdelacabeza: https://github.com/andor-pierdelacabeza
|
||||||
.. _@antoniablair: https://github.com/antoniablair
|
.. _@antoniablair: https://github.com/antoniablair
|
||||||
|
.. _@archinal: https://github.com/archinal
|
||||||
.. _@areski: https://github.com/areski
|
.. _@areski: https://github.com/areski
|
||||||
.. _@arruda: https://github.com/arruda
|
.. _@arruda: https://github.com/arruda
|
||||||
.. _@bittner: https://github.com/bittner
|
.. _@bittner: https://github.com/bittner
|
||||||
|
@ -186,17 +200,22 @@ Listed in alphabetical order.
|
||||||
.. _@knitatoms: https://github.com/knitatoms
|
.. _@knitatoms: https://github.com/knitatoms
|
||||||
.. _@krzysztofzuraw: https://github.com/krzysztofzuraw
|
.. _@krzysztofzuraw: https://github.com/krzysztofzuraw
|
||||||
.. _@MathijsHoogland: https://github.com/MathijsHoogland
|
.. _@MathijsHoogland: https://github.com/MathijsHoogland
|
||||||
|
.. _@mattayes: https://github.com/mattayes
|
||||||
.. _@menzenski: https://github.com/menzenski
|
.. _@menzenski: https://github.com/menzenski
|
||||||
.. _@mfwarren: https://github.com/mfwarren
|
.. _@mfwarren: https://github.com/mfwarren
|
||||||
|
.. _@mimischi: https://github.com/mimischi
|
||||||
.. _@mjsisley: https://github.com/mjsisley
|
.. _@mjsisley: https://github.com/mjsisley
|
||||||
|
.. _@myilmaz: https://github.com/myilmaz
|
||||||
.. _@mozillazg: https://github.com/mozillazg
|
.. _@mozillazg: https://github.com/mozillazg
|
||||||
.. _@noisy: https://github.com/noisy
|
.. _@noisy: https://github.com/noisy
|
||||||
.. _@originell: https://github.com/originell
|
.. _@originell: https://github.com/originell
|
||||||
.. _@oubiga: https://github.com/oubiga
|
.. _@oubiga: https://github.com/oubiga
|
||||||
.. _@parbhat: https://github.com/parbhat
|
.. _@parbhat: https://github.com/parbhat
|
||||||
.. _@raonyguimaraes: https://github.com/raonyguimaraes
|
.. _@raonyguimaraes: https://github.com/raonyguimaraes
|
||||||
|
.. _@rm--: https://github.com/rm--
|
||||||
.. _@romanosipenko: https://github.com/romanosipenko
|
.. _@romanosipenko: https://github.com/romanosipenko
|
||||||
.. _@shireenrao: https://github.com/shireenrao
|
.. _@shireenrao: https://github.com/shireenrao
|
||||||
|
.. _@webyneter: https://github.com/webyneter
|
||||||
.. _@show0k: https://github.com/show0k
|
.. _@show0k: https://github.com/show0k
|
||||||
.. _@shultz: https://github.com/shultz
|
.. _@shultz: https://github.com/shultz
|
||||||
.. _@siauPatrick: https://github.com/siauPatrick
|
.. _@siauPatrick: https://github.com/siauPatrick
|
||||||
|
@ -204,6 +223,7 @@ Listed in alphabetical order.
|
||||||
.. _@ssteinerX: https://github.com/ssteinerx
|
.. _@ssteinerX: https://github.com/ssteinerx
|
||||||
.. _@stepmr: https://github.com/stepmr
|
.. _@stepmr: https://github.com/stepmr
|
||||||
.. _@suledev: https://github.com/suledev
|
.. _@suledev: https://github.com/suledev
|
||||||
|
.. _@timfreund: https://github.com/timfreund
|
||||||
.. _@Travistock: https://github.com/Tavistock
|
.. _@Travistock: https://github.com/Tavistock
|
||||||
.. _@trungdong: https://github.com/trungdong
|
.. _@trungdong: https://github.com/trungdong
|
||||||
.. _@viviangb: httpsL//github.com/viviangb
|
.. _@viviangb: httpsL//github.com/viviangb
|
||||||
|
@ -214,6 +234,8 @@ Listed in alphabetical order.
|
||||||
.. _@sladinji: https://github.com/sladinji
|
.. _@sladinji: https://github.com/sladinji
|
||||||
.. _@andresgz: https://github.com/andresgz
|
.. _@andresgz: https://github.com/andresgz
|
||||||
.. _@jangeador: https://github.com/jangeador
|
.. _@jangeador: https://github.com/jangeador
|
||||||
|
.. _@townie: https://github.com/townie
|
||||||
|
.. _@MightySCollins: https://github.com/MightySCollins
|
||||||
|
|
||||||
Special Thanks
|
Special Thanks
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
55
README.rst
55
README.rst
|
@ -16,20 +16,24 @@ Powered by Cookiecutter_, Cookiecutter Django is a framework for jumpstarting pr
|
||||||
|
|
||||||
* Documentation: https://cookiecutter-django.readthedocs.io/en/latest/
|
* Documentation: https://cookiecutter-django.readthedocs.io/en/latest/
|
||||||
* See Troubleshooting_ for common errors and obstacles
|
* See Troubleshooting_ for common errors and obstacles
|
||||||
|
* If you have problems with Cookiecutter Django, please open issues_ before sending emails to the maintainers. You will get a much, MUCH faster response.
|
||||||
|
|
||||||
.. _cookiecutter: https://github.com/audreyr/cookiecutter
|
.. _cookiecutter: https://github.com/audreyr/cookiecutter
|
||||||
|
|
||||||
.. _Troubleshooting: https://cookiecutter-django.readthedocs.io/en/latest/troubleshooting.html
|
.. _Troubleshooting: https://cookiecutter-django.readthedocs.io/en/latest/troubleshooting.html
|
||||||
|
|
||||||
.. _528: https://github.com/pydanny/cookiecutter-django/issues/528#issuecomment-212650373
|
.. _528: https://github.com/pydanny/cookiecutter-django/issues/528#issuecomment-212650373
|
||||||
|
.. _issues: https://github.com/pydanny/cookiecutter-django/issues/new
|
||||||
|
|
||||||
Features
|
Features
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* For Django 1.9
|
* For Django 1.10
|
||||||
|
* Works with Python 3.4.x or 3.5.x. Python 3.6 is experimental
|
||||||
* Renders Django projects with 100% starting test coverage
|
* Renders Django projects with 100% starting test coverage
|
||||||
* Twitter Bootstrap_ v4.0.0 - `alpha 3`_
|
* Twitter Bootstrap_ v4.0.0 - alpha 6 (`maintained Foundation fork`_ also available)
|
||||||
* 12-Factor_ based settings via django-environ_
|
* 12-Factor_ based settings via django-environ_
|
||||||
|
* Secure by default. We believe in SSL.
|
||||||
* Optimized development and production settings
|
* Optimized development and production settings
|
||||||
* Registration via django-allauth_
|
* Registration via django-allauth_
|
||||||
* Comes with custom user model ready to go
|
* Comes with custom user model ready to go
|
||||||
|
@ -39,9 +43,11 @@ Features
|
||||||
* Docker support using docker-compose_ for development and production
|
* Docker support using docker-compose_ for development and production
|
||||||
* Procfile_ for deploying to Heroku
|
* Procfile_ for deploying to Heroku
|
||||||
* Instructions for deploying to PythonAnywhere_
|
* Instructions for deploying to PythonAnywhere_
|
||||||
* Works with Python 2.7.x or 3.5.x
|
|
||||||
* Run tests with unittest or py.test
|
* Run tests with unittest or py.test
|
||||||
* Customizable PostgreSQL version
|
* Customizable PostgreSQL version
|
||||||
|
* Experimental support for Amazon Elastic Beanstalk
|
||||||
|
|
||||||
|
.. _`maintained Foundation fork`: https://github.com/Parbhat/cookiecutter-django-foundation
|
||||||
|
|
||||||
|
|
||||||
Optional Integrations
|
Optional Integrations
|
||||||
|
@ -55,7 +61,6 @@ Optional Integrations
|
||||||
* Integration with Sentry_ for error logging
|
* Integration with Sentry_ for error logging
|
||||||
* Integration with Opbeat_ for performance monitoring
|
* Integration with Opbeat_ for performance monitoring
|
||||||
|
|
||||||
.. _`alpha 3`: http://blog.getbootstrap.com/2016/07/27/bootstrap-4-alpha-3/
|
|
||||||
.. _Bootstrap: https://github.com/twbs/bootstrap
|
.. _Bootstrap: https://github.com/twbs/bootstrap
|
||||||
.. _django-environ: https://github.com/joke2k/django-environ
|
.. _django-environ: https://github.com/joke2k/django-environ
|
||||||
.. _12-Factor: http://12factor.net/
|
.. _12-Factor: http://12factor.net/
|
||||||
|
@ -67,7 +72,7 @@ Optional Integrations
|
||||||
.. _Celery: http://www.celeryproject.org/
|
.. _Celery: http://www.celeryproject.org/
|
||||||
.. _Anymail: https://github.com/anymail/django-anymail
|
.. _Anymail: https://github.com/anymail/django-anymail
|
||||||
.. _MailHog: https://github.com/mailhog/MailHog
|
.. _MailHog: https://github.com/mailhog/MailHog
|
||||||
.. _Sentry: https://getsentry.com/welcome/
|
.. _Sentry: https://sentry.io/welcome/
|
||||||
.. _docker-compose: https://github.com/docker/compose
|
.. _docker-compose: https://github.com/docker/compose
|
||||||
.. _Opbeat: https://opbeat.com/
|
.. _Opbeat: https://opbeat.com/
|
||||||
.. _PythonAnywhere: https://www.pythonanywhere.com/
|
.. _PythonAnywhere: https://www.pythonanywhere.com/
|
||||||
|
@ -78,7 +83,7 @@ Constraints
|
||||||
|
|
||||||
* Only maintained 3rd party libraries are used.
|
* Only maintained 3rd party libraries are used.
|
||||||
* Uses PostgreSQL everywhere (9.2+)
|
* Uses PostgreSQL everywhere (9.2+)
|
||||||
* Environment variables for configuration (This won't work with Apache/mod_wsgi).
|
* Environment variables for configuration (This won't work with Apache/mod_wsgi except on AWS ELB).
|
||||||
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
|
@ -89,7 +94,7 @@ and then editing the results to include your name, email, and various configurat
|
||||||
|
|
||||||
First, get Cookiecutter. Trust me, it's awesome::
|
First, get Cookiecutter. Trust me, it's awesome::
|
||||||
|
|
||||||
$ pip install cookiecutter
|
$ pip install "cookiecutter>=1.4.0"
|
||||||
|
|
||||||
Now run it against this repo::
|
Now run it against this repo::
|
||||||
|
|
||||||
|
@ -122,7 +127,6 @@ Answer the prompts with your own desired options_. For example::
|
||||||
use_opbeat [n]: y
|
use_opbeat [n]: y
|
||||||
use_pycharm [n]: y
|
use_pycharm [n]: y
|
||||||
windows [n]: n
|
windows [n]: n
|
||||||
use_python3 [y]: y
|
|
||||||
use_docker [y]: n
|
use_docker [y]: n
|
||||||
use_heroku [n]: y
|
use_heroku [n]: y
|
||||||
use_compressor [n]: y
|
use_compressor [n]: y
|
||||||
|
@ -135,8 +139,7 @@ Answer the prompts with your own desired options_. For example::
|
||||||
Select js_task_runner:
|
Select js_task_runner:
|
||||||
1 - Gulp
|
1 - Gulp
|
||||||
2 - Grunt
|
2 - Grunt
|
||||||
3 - Webpack
|
3 - None
|
||||||
4 - None
|
|
||||||
Choose from 1, 2, 3, 4 [1]: 1
|
Choose from 1, 2, 3, 4 [1]: 1
|
||||||
use_lets_encrypt [n]: n
|
use_lets_encrypt [n]: n
|
||||||
Select open_source_license:
|
Select open_source_license:
|
||||||
|
@ -146,6 +149,7 @@ Answer the prompts with your own desired options_. For example::
|
||||||
4 - Apache Software License 2.0
|
4 - Apache Software License 2.0
|
||||||
5 - Not open source
|
5 - Not open source
|
||||||
Choose from 1, 2, 3, 4, 5 [1]: 1
|
Choose from 1, 2, 3, 4, 5 [1]: 1
|
||||||
|
use_elasticbeanstalk_experimental: n
|
||||||
|
|
||||||
Enter the project and take a look around::
|
Enter the project and take a look around::
|
||||||
|
|
||||||
|
@ -187,6 +191,13 @@ For Readers of Two Scoops of Django 1.8
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
For pyup.io Users
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
If you are using `pyup.io`_ to keep your dependencies updated and secure, use the code *cookiecutter* during checkout to get 15% off every month.
|
||||||
|
|
||||||
|
.. _`pyup.io`: https://pyup.io
|
||||||
|
|
||||||
"Your Stuff"
|
"Your Stuff"
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
@ -252,10 +263,26 @@ Support This Project
|
||||||
|
|
||||||
This project is maintained by volunteers. Support their efforts by spreading the word about:
|
This project is maintained by volunteers. Support their efforts by spreading the word about:
|
||||||
|
|
||||||
.. image:: https://s3.amazonaws.com/tsacademy/images/tsa-logo-250x60-transparent-01.png
|
Two Scoops of Django 1.11
|
||||||
:name: Two Scoops Academy
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. image:: https://cdn.shopify.com/s/files/1/0304/6901/files/tsd-111-alpha-470x235.jpg?2934688328290951771
|
||||||
|
:name: Two Scoops of Django 1.11 Cover
|
||||||
:align: center
|
:align: center
|
||||||
:alt: Two Scoops Academy
|
:alt: Two Scoops of Django
|
||||||
:target: https://twoscoops.academy/
|
:target: http://twoscoopspress.org/products/two-scoops-of-django-1-11
|
||||||
|
|
||||||
|
Two Scoops of Django is the best dairy-themed Django reference in the universe
|
||||||
|
|
||||||
|
pyup
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. image:: https://pyup.io/static/images/logo.png
|
||||||
|
:name: pyup
|
||||||
|
:align: center
|
||||||
|
:alt: pyup
|
||||||
|
:target: https://pyup.io/
|
||||||
|
|
||||||
|
Pyup brings you automated security and dependency updates used by Google and other organizations. Free for open source projects!
|
||||||
|
|
||||||
.. _`PyPA Code of Conduct`: https://www.pypa.io/en/latest/code-of-conduct/
|
.. _`PyPA Code of Conduct`: https://www.pypa.io/en/latest/code-of-conduct/
|
||||||
|
|
|
@ -14,11 +14,11 @@
|
||||||
"use_opbeat": "n",
|
"use_opbeat": "n",
|
||||||
"use_pycharm": "n",
|
"use_pycharm": "n",
|
||||||
"windows": "n",
|
"windows": "n",
|
||||||
"use_python3": "y",
|
"use_docker": "n",
|
||||||
"use_docker": "y",
|
|
||||||
"use_heroku": "n",
|
"use_heroku": "n",
|
||||||
|
"use_elasticbeanstalk_experimental": "n",
|
||||||
"use_compressor": "n",
|
"use_compressor": "n",
|
||||||
"postgresql_version": ["9.5", "9.4", "9.3", "9.2"],
|
"postgresql_version": ["9.6", "9.5", "9.4", "9.3", "9.2"],
|
||||||
"js_task_runner": ["Gulp", "Grunt", "None"],
|
"js_task_runner": ["Gulp", "Grunt", "None"],
|
||||||
"use_lets_encrypt": "n",
|
"use_lets_encrypt": "n",
|
||||||
"open_source_license": ["MIT", "BSD", "GPLv3", "Apache Software License 2.0", "Not open source"]
|
"open_source_license": ["MIT", "BSD", "GPLv3", "Apache Software License 2.0", "Not open source"]
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# cookiecutter-django documentation build configuration file.
|
# cookiecutter-django documentation build configuration file.
|
||||||
#
|
#
|
||||||
# This file is execfile()d with the current directory set to its containing dir.
|
# This file is execfile()d with the current directory set to its containing dir.
|
||||||
|
@ -10,8 +8,6 @@
|
||||||
# All configuration values have a default; values that are commented out
|
# All configuration values have a default; values that are commented out
|
||||||
# serve to show the default.
|
# serve to show the default.
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
|
@ -3,7 +3,7 @@ Deployment on Heroku
|
||||||
|
|
||||||
.. index:: Heroku
|
.. index:: Heroku
|
||||||
|
|
||||||
You can either push the 'deploy' button in your generated README.rst or run these commands to deploy the project to Heroku:
|
Run these commands to deploy the project to Heroku:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ You can either push the 'deploy' button in your generated README.rst or run thes
|
||||||
|
|
||||||
heroku config:set DJANGO_MAILGUN_SERVER_NAME=YOUR_MALGUN_SERVER
|
heroku config:set DJANGO_MAILGUN_SERVER_NAME=YOUR_MALGUN_SERVER
|
||||||
heroku config:set DJANGO_MAILGUN_API_KEY=YOUR_MAILGUN_API_KEY
|
heroku config:set DJANGO_MAILGUN_API_KEY=YOUR_MAILGUN_API_KEY
|
||||||
|
heroku config:set MAILGUN_SENDER_DOMAIN=YOUR_MAILGUN_SENDER_DOMAIN
|
||||||
|
|
||||||
heroku config:set PYTHONHASHSEED=random
|
heroku config:set PYTHONHASHSEED=random
|
||||||
heroku config:set DJANGO_ADMIN_URL=\^somelocation/
|
heroku config:set DJANGO_ADMIN_URL=\^somelocation/
|
||||||
|
|
|
@ -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
|
git clone <my-repo-url> # you can also use hg
|
||||||
cd my-project-name
|
cd my-project-name
|
||||||
mkvirtualenv --python=/usr/bin/python3.5 my-project-name # or python2.7, etc
|
mkvirtualenv --python=/usr/bin/python3.5 my-project-name
|
||||||
pip install -r requirements/production.txt # may take a few minutes
|
pip install -r requirements/production.txt # may take a few minutes
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ Generate a secret key for yourself, eg like this:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
python -c 'import random; print("".join(random.SystemRandom().choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") for _ in range(50)))'
|
python -c 'import random;import string; print("".join(random.SystemRandom().choice(string.digits + string.ascii_letters + string.punctuation) for _ in range(50)))'
|
||||||
|
|
||||||
Make a note of it, since we'll need it here in the console and later on in the web app config tab.
|
Make a note of it, since we'll need it here in the console and later on in the web app config tab.
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ Add these exports
|
||||||
export DJANGO_ADMIN_URL='<not admin/>'
|
export DJANGO_ADMIN_URL='<not admin/>'
|
||||||
export DJANGO_MAILGUN_API_KEY='<mailgun key>'
|
export DJANGO_MAILGUN_API_KEY='<mailgun key>'
|
||||||
export DJANGO_MAILGUN_SERVER_NAME='<mailgun server name>'
|
export DJANGO_MAILGUN_SERVER_NAME='<mailgun server name>'
|
||||||
|
export MAILGUN_SENDER_DOMAIN='<mailgun sender domain (e.g. mg.yourdomain.com)>'
|
||||||
export DJANGO_AWS_ACCESS_KEY_ID=
|
export DJANGO_AWS_ACCESS_KEY_ID=
|
||||||
export DJANGO_AWS_SECRET_ACCESS_KEY=
|
export DJANGO_AWS_SECRET_ACCESS_KEY=
|
||||||
export DJANGO_AWS_STORAGE_BUCKET_NAME=
|
export DJANGO_AWS_STORAGE_BUCKET_NAME=
|
||||||
|
@ -139,6 +140,7 @@ Click through to the **WSGI configuration file** link (near the top) and edit th
|
||||||
os.environ['DJANGO_ADMIN_URL'] = '<as above>'
|
os.environ['DJANGO_ADMIN_URL'] = '<as above>'
|
||||||
os.environ['DJANGO_MAILGUN_API_KEY'] = '<as above>'
|
os.environ['DJANGO_MAILGUN_API_KEY'] = '<as above>'
|
||||||
os.environ['DJANGO_MAILGUN_SERVER_NAME'] = '<as above>'
|
os.environ['DJANGO_MAILGUN_SERVER_NAME'] = '<as above>'
|
||||||
|
os.environ['MAILGUN_SENDER_DOMAIN'] = '<as above>'
|
||||||
os.environ['DJANGO_AWS_ACCESS_KEY_ID'] = ''
|
os.environ['DJANGO_AWS_ACCESS_KEY_ID'] = ''
|
||||||
os.environ['DJANGO_AWS_SECRET_ACCESS_KEY'] = ''
|
os.environ['DJANGO_AWS_SECRET_ACCESS_KEY'] = ''
|
||||||
os.environ['DJANGO_AWS_STORAGE_BUCKET_NAME'] = ''
|
os.environ['DJANGO_AWS_STORAGE_BUCKET_NAME'] = ''
|
||||||
|
@ -178,5 +180,3 @@ For subsequent deployments, the procedure is much simpler. In a Bash console:
|
||||||
And then go to the Web tab and hit **Reload**
|
And then go to the Web tab and hit **Reload**
|
||||||
|
|
||||||
**TIP:** *if you're really keen, you can set up git-push based deployments: https://blog.pythonanywhere.com/87/*
|
**TIP:** *if you're really keen, you can set up git-push based deployments: https://blog.pythonanywhere.com/87/*
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,26 @@ root directory of this project as a starting point. Add your own variables to th
|
||||||
file won't be tracked by git by default so you'll have to make sure to use some other mechanism to copy your secret if
|
file won't be tracked by git by default so you'll have to make sure to use some other mechanism to copy your secret if
|
||||||
you are relying solely on git.
|
you are relying solely on git.
|
||||||
|
|
||||||
|
To obtain logs and information about crashes in a production setup, make sure that you have access to an external Sentry instance (e.g. by creating an account with `sentry.io`_), and set the `DJANGO_SENTRY_DSN` variable. This should be enough to report crashes to Sentry.
|
||||||
|
|
||||||
|
You will probably also need to setup the Mail backend, for example by adding a `Mailgun`_ API key and a `Mailgun`_ sender domain, otherwise, the account creation view will crash and result in a 500 error when the backend attempts to send an email to the account owner.
|
||||||
|
|
||||||
|
.. _sentry.io: https://sentry.io/welcome
|
||||||
|
.. _Mailgun: https://mailgun.com
|
||||||
|
|
||||||
|
HTTPS is on by default
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
SSL (Secure Sockets Layer) is a standard security technology for establishing an encrypted link between a server and a client, typically in this case, a web server (website) and a browser. Not having HTTPS means that malicious network users can sniff authentication credentials between your website and end users' browser.
|
||||||
|
|
||||||
|
It is always better to deploy a site behind HTTPS and will become crucial as the web services extend to the IoT (Internet of Things). For this reason, we have set up a number of security defaults to help make your website secure:
|
||||||
|
|
||||||
|
* In the `.env.example`, we have made it simpler for you to change the default `Django Admin` into a custom name through an environmental variable. This should make it harder to guess the access to the admin panel.
|
||||||
|
|
||||||
|
* If you are not using a subdomain of the domain name set in the project, then remember to put the your staging/production IP address in the ``ALLOWED_HOSTS``_ environment variable before you deploy your website. Failure to do this will mean you will not have access to your website through the HTTP protocol.
|
||||||
|
|
||||||
|
* Access to the Django admin is set up by default to require HTTPS in production or once *live*. We recommend that you look into setting up the *Certbot and Let's Encrypt Setup* mentioned below or another HTTPS certification service.
|
||||||
|
|
||||||
Optional: nginx-proxy Setup
|
Optional: nginx-proxy Setup
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
@ -52,8 +72,7 @@ This pass all incoming requests on `nginx-proxy`_ to the nginx service your appl
|
||||||
Optional: Postgres Data Volume Modifications
|
Optional: Postgres Data Volume Modifications
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
Postgres is saving its database files to the `postgres_data` volume by default. Change that if you wan't
|
Postgres is saving its database files to the `postgres_data` volume by default. Change that if you want something else and make sure to make backups since this is not done automatically.
|
||||||
something else and make sure to make backups since this is not done automatically.
|
|
||||||
|
|
||||||
Optional: Certbot and Let's Encrypt Setup
|
Optional: Certbot and Let's Encrypt Setup
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
@ -90,7 +109,7 @@ If you would like to set up autorenewal of your certificates, the following comm
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
cd <project directory>
|
cd <project directory>
|
||||||
docker-compose run --rm --name certbot certbot bash -c "sleep 6 && certbot certonly --standalone -d {{ cookiecutter.domain_name }} --text --agree-tos --email {{ cookiecutter.email }} --server https://acme-v01.api.letsencrypt.org/directory --rsa-key-size 4096 --verbose --keep-until-expiring --standalone-supported-challenges http-01"
|
docker-compose run --rm --name certbot certbot bash -c "sleep 6 && certbot certonly --standalone -d {{ cookiecutter.domain_name }} --text --agree-tos --email {{ cookiecutter.email }} --server https://acme-v01.api.letsencrypt.org/directory --rsa-key-size 4096 --verbose --keep-until-expiring --standalone-supported-challenges http-01"
|
||||||
docker exec pearl_nginx_1 nginx -s reload
|
docker exec {{ cookiecutter.project_name }}_nginx_1 nginx -s reload
|
||||||
|
|
||||||
And then set a cronjob by running `crontab -e` and placing in it (period can be adjusted as desired)::
|
And then set a cronjob by running `crontab -e` and placing in it (period can be adjusted as desired)::
|
||||||
|
|
||||||
|
@ -143,7 +162,7 @@ If you have errors, you can always check your stack with `docker-compose`. Switc
|
||||||
Supervisor Example
|
Supervisor Example
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Once you are ready with your initial setup, you wan't to make sure that your application is run by a process manager to
|
Once you are ready with your initial setup, you want to make sure that your application is run by a process manager to
|
||||||
survive reboots and auto restarts in case of an error. You can use the process manager you are most familiar with. All
|
survive reboots and auto restarts in case of an error. You can use the process manager you are most familiar with. All
|
||||||
it needs to do is to run `docker-compose up` in your projects root directory.
|
it needs to do is to run `docker-compose up` in your projects root directory.
|
||||||
|
|
||||||
|
|
72
docs/deployment-with-elastic-beanstalk.rst
Normal file
72
docs/deployment-with-elastic-beanstalk.rst
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
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.
|
|
@ -20,6 +20,16 @@ If you don't already have it installed, follow the instructions for your OS:
|
||||||
.. _`Docker for Windows`: https://docs.docker.com/engine/installation/windows/
|
.. _`Docker for Windows`: https://docs.docker.com/engine/installation/windows/
|
||||||
.. _`docker-engine`: https://docs.docker.com/engine/installation/
|
.. _`docker-engine`: https://docs.docker.com/engine/installation/
|
||||||
|
|
||||||
|
Attention Windows users
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Currently PostgreSQL (``psycopg2`` python package) is not installed inside Docker containers for Windows users, while it is required by the generated Django project. To fix this, add ``psycopg2`` to the list of requirements inside ``requirements/base.txt``::
|
||||||
|
|
||||||
|
# Python-PostgreSQL Database Adapter
|
||||||
|
psycopg2==2.6.2
|
||||||
|
|
||||||
|
Doing this will prevent the project from being installed in an Windows-only environment (thus without usage of Docker). If you want to use this project without Docker, make sure to remove ``psycopg2`` from the requirements again.
|
||||||
|
|
||||||
Build the Stack
|
Build the Stack
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -63,6 +73,11 @@ To migrate your app and to create a superuser, run::
|
||||||
|
|
||||||
Here we specify the ``django`` container as the location to run our management commands.
|
Here we specify the ``django`` container as the location to run our management commands.
|
||||||
|
|
||||||
|
Add your Docker development server IP
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
When ``DEBUG`` is set to `True`, the host is validated against ``['localhost', '127.0.0.1', '[::1]']``. This is adequate when running a ``virtualenv``. For Docker, in the ``config.settings.local``, add your host development server IP to ``INTERNAL_IPS`` or ``ALLOWED_HOSTS`` if the variable exists.
|
||||||
|
|
||||||
Production Mode
|
Production Mode
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ Setup your email backend
|
||||||
|
|
||||||
django-allauth sends an email to verify users (and superusers) after signup and login (if they are still not verified). To send email you need to `configure your email backend`_
|
django-allauth sends an email to verify users (and superusers) after signup and login (if they are still not verified). To send email you need to `configure your email backend`_
|
||||||
|
|
||||||
.. _configure your email backend: http://docs.djangoproject.com/en/1.9/topics/email/#smtp-backend
|
.. _configure your email backend: https://docs.djangoproject.com/en/dev/topics/email/#smtp-backend
|
||||||
|
|
||||||
In development you can (optionally) use MailHog_ for email testing. MailHog is built with Go so there are no dependencies. To use MailHog:
|
In development you can (optionally) use MailHog_ for email testing. MailHog is built with Go so there are no dependencies. To use MailHog:
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,9 @@ Why is there a django.contrib.sites directory in Cookiecutter Django?
|
||||||
|
|
||||||
It is there to add a migration so you don't have to manually change the ``sites.Site`` record from ``example.com`` to whatever your domain is. Instead, your ``{{cookiecutter.domain_name}}`` and {{cookiecutter.project_name}} value is placed by **Cookiecutter** in the domain and name fields respectively.
|
It is there to add a migration so you don't have to manually change the ``sites.Site`` record from ``example.com`` to whatever your domain is. Instead, your ``{{cookiecutter.domain_name}}`` and {{cookiecutter.project_name}} value is placed by **Cookiecutter** in the domain and name fields respectively.
|
||||||
|
|
||||||
See `0002_set_site_domain_and_name.py`_.
|
See `0003_set_site_domain_and_name.py`_.
|
||||||
|
|
||||||
.. _`0002_set_site_domain_and_name.py`: https://github.com/pydanny/cookiecutter-django/blob/master/%7B%7Bcookiecutter.project_slug%7D%7D/%7B%7Bcookiecutter.project_slug%7D%7D/contrib/sites/migrations/0002_set_site_domain_and_name.py
|
.. _`0003_set_site_domain_and_name.py`: https://github.com/pydanny/cookiecutter-django/blob/master/%7B%7Bcookiecutter.project_slug%7D%7D/%7B%7Bcookiecutter.project_slug%7D%7D/contrib/sites/migrations/0003_set_site_domain_and_name.py
|
||||||
|
|
||||||
|
|
||||||
Why aren't you using just one configuration file (12-Factor App)
|
Why aren't you using just one configuration file (12-Factor App)
|
||||||
|
|
|
@ -25,6 +25,7 @@ Contents:
|
||||||
faq
|
faq
|
||||||
troubleshooting
|
troubleshooting
|
||||||
my-favorite-cookie
|
my-favorite-cookie
|
||||||
|
deployment-with-elastic-beanstalk
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
|
|
@ -25,7 +25,7 @@ version [0.1.0]
|
||||||
The starting version number for your project.
|
The starting version number for your project.
|
||||||
|
|
||||||
timezone [UTC]
|
timezone [UTC]
|
||||||
Used in the common settings file for the `TIME_ZONE` value.
|
Used in the base settings file for the `TIME_ZONE` value.
|
||||||
|
|
||||||
use_whitenoise [y]
|
use_whitenoise [y]
|
||||||
Whether to use WhiteNoise_ for static file serving.
|
Whether to use WhiteNoise_ for static file serving.
|
||||||
|
@ -54,10 +54,6 @@ use_pycharm [n]
|
||||||
windows [n]
|
windows [n]
|
||||||
Whether you'll be developing on Windows.
|
Whether you'll be developing on Windows.
|
||||||
|
|
||||||
use_python3 [y]
|
|
||||||
By default, the Python code generated will be for Python 3.x. But if you
|
|
||||||
answer `n` here, it will be legacy Python 2.7 code.
|
|
||||||
|
|
||||||
use_docker [y]
|
use_docker [y]
|
||||||
Whether to use Docker_, separating the app and database into separate
|
Whether to use Docker_, separating the app and database into separate
|
||||||
containers.
|
containers.
|
||||||
|
@ -74,8 +70,7 @@ js_task_runner [1]
|
||||||
|
|
||||||
1. Gulp_
|
1. Gulp_
|
||||||
2. Grunt_
|
2. Grunt_
|
||||||
3. Webpack_
|
3. None
|
||||||
4. None
|
|
||||||
|
|
||||||
use_lets_encrypt [n]
|
use_lets_encrypt [n]
|
||||||
Use `Let's Encrypt`_ as the certificate authority for this project.
|
Use `Let's Encrypt`_ as the certificate authority for this project.
|
||||||
|
|
|
@ -3,7 +3,14 @@ Settings
|
||||||
|
|
||||||
This project relies extensively on environment settings which **will not work with Apache/mod_wsgi setups**. It has been deployed successfully with both Gunicorn/Nginx and even uWSGI/Nginx.
|
This project relies extensively on environment settings which **will not work with Apache/mod_wsgi setups**. It has been deployed successfully with both Gunicorn/Nginx and even uWSGI/Nginx.
|
||||||
|
|
||||||
For configuration purposes, the following table maps environment variables to their Django setting:
|
For configuration purposes, the following table maps environment variables to their Django setting and project settings:
|
||||||
|
|
||||||
|
|
||||||
|
======================================= =========================== ============================================== ======================================================================
|
||||||
|
Environment Variable Django Setting Development Default Production Default
|
||||||
|
======================================= =========================== ============================================== ======================================================================
|
||||||
|
DJANGO_READ_DOT_ENV_FILE READ_DOT_ENV_FILE False False
|
||||||
|
======================================= =========================== ============================================== ======================================================================
|
||||||
|
|
||||||
|
|
||||||
======================================= =========================== ============================================== ======================================================================
|
======================================= =========================== ============================================== ======================================================================
|
||||||
|
@ -40,6 +47,7 @@ DJANGO_SENTRY_CLIENT SENTRY_CLIENT n/a
|
||||||
DJANGO_SENTRY_LOG_LEVEL SENTRY_LOG_LEVEL n/a logging.INFO
|
DJANGO_SENTRY_LOG_LEVEL SENTRY_LOG_LEVEL n/a logging.INFO
|
||||||
DJANGO_MAILGUN_API_KEY MAILGUN_ACCESS_KEY n/a raises error
|
DJANGO_MAILGUN_API_KEY MAILGUN_ACCESS_KEY n/a raises error
|
||||||
DJANGO_MAILGUN_SERVER_NAME MAILGUN_SERVER_NAME 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
|
||||||
NEW_RELIC_APP_NAME NEW_RELIC_APP_NAME n/a raises error
|
NEW_RELIC_APP_NAME NEW_RELIC_APP_NAME n/a raises error
|
||||||
NEW_RELIC_LICENSE_KEY NEW_RELIC_LICENSE_KEY n/a raises error
|
NEW_RELIC_LICENSE_KEY NEW_RELIC_LICENSE_KEY n/a raises error
|
||||||
DJANGO_OPBEAT_APP_ID OPBEAT['APP_ID'] n/a raises error
|
DJANGO_OPBEAT_APP_ID OPBEAT['APP_ID'] n/a raises error
|
||||||
|
|
|
@ -12,10 +12,10 @@ A portion of this code was adopted from Django's standard crypto functions and
|
||||||
utilities, specifically:
|
utilities, specifically:
|
||||||
https://github.com/django/django/blob/master/django/utils/crypto.py
|
https://github.com/django/django/blob/master/django/utils/crypto.py
|
||||||
"""
|
"""
|
||||||
from __future__ import print_function
|
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import shutil
|
import shutil
|
||||||
|
import string
|
||||||
|
|
||||||
# Get the root project directory
|
# Get the root project directory
|
||||||
PROJECT_DIRECTORY = os.path.realpath(os.path.curdir)
|
PROJECT_DIRECTORY = os.path.realpath(os.path.curdir)
|
||||||
|
@ -28,16 +28,19 @@ except NotImplementedError:
|
||||||
using_sysrandom = False
|
using_sysrandom = False
|
||||||
|
|
||||||
|
|
||||||
def get_random_string(
|
def get_random_string(length=50):
|
||||||
length=50,
|
|
||||||
allowed_chars='abcdefghijklmnopqrstuvwxyz0123456789!@#%^&*(-_=+)'):
|
|
||||||
"""
|
"""
|
||||||
Returns a securely generated random string.
|
Returns a securely generated random string.
|
||||||
The default length of 12 with the a-z, A-Z, 0-9 character set returns
|
The default length of 12 with the a-z, A-Z, 0-9 character set returns
|
||||||
a 71-bit value. log_2((26+26+10)^12) =~ 71 bits
|
a 71-bit value. log_2((26+26+10)^12) =~ 71 bits
|
||||||
"""
|
"""
|
||||||
|
punctuation = string.punctuation.replace('"', '').replace("'", '')
|
||||||
|
punctuation = punctuation.replace('\\', '')
|
||||||
if using_sysrandom:
|
if using_sysrandom:
|
||||||
return ''.join(random.choice(allowed_chars) for i in range(length))
|
return ''.join(random.choice(
|
||||||
|
string.digits + string.ascii_letters + punctuation
|
||||||
|
) for i in range(length))
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"Cookiecutter Django couldn't find a secure pseudo-random number generator on your system."
|
"Cookiecutter Django couldn't find a secure pseudo-random number generator on your system."
|
||||||
" Please change change your SECRET_KEY variables in conf/settings/local.py and env.example"
|
" Please change change your SECRET_KEY variables in conf/settings/local.py and env.example"
|
||||||
|
@ -115,7 +118,10 @@ def remove_heroku_files():
|
||||||
"""
|
"""
|
||||||
Removes files needed for heroku if it isn't going to be used
|
Removes files needed for heroku if it isn't going to be used
|
||||||
"""
|
"""
|
||||||
for filename in ["app.json", "Procfile", "requirements.txt", "runtime.txt"]:
|
filenames = ["Procfile", "runtime.txt"]
|
||||||
|
if '{{ cookiecutter.use_elasticbeanstalk_experimental }}'.lower() != 'y':
|
||||||
|
filenames.append("requirements.txt")
|
||||||
|
for filename in ["Procfile", "runtime.txt"]:
|
||||||
file_name = os.path.join(PROJECT_DIRECTORY, filename)
|
file_name = os.path.join(PROJECT_DIRECTORY, filename)
|
||||||
remove_file(file_name)
|
remove_file(file_name)
|
||||||
|
|
||||||
|
@ -179,6 +185,32 @@ def remove_copying_files():
|
||||||
PROJECT_DIRECTORY, filename
|
PROJECT_DIRECTORY, filename
|
||||||
))
|
))
|
||||||
|
|
||||||
|
def remove_elasticbeanstalk():
|
||||||
|
"""
|
||||||
|
Removes elastic beanstalk components
|
||||||
|
"""
|
||||||
|
docs_dir_location = os.path.join(PROJECT_DIRECTORY, '.ebextensions')
|
||||||
|
if os.path.exists(docs_dir_location):
|
||||||
|
shutil.rmtree(docs_dir_location)
|
||||||
|
|
||||||
|
filenames = ["ebsetenv.py", ]
|
||||||
|
if '{{ cookiecutter.use_heroku }}'.lower() != 'y':
|
||||||
|
filenames.append("requirements.txt")
|
||||||
|
for filename in filenames:
|
||||||
|
os.remove(os.path.join(
|
||||||
|
PROJECT_DIRECTORY, filename
|
||||||
|
))
|
||||||
|
|
||||||
|
def remove_open_source_files():
|
||||||
|
"""
|
||||||
|
Removes files conventional to opensource projects only.
|
||||||
|
"""
|
||||||
|
for filename in ["CONTRIBUTORS.txt"]:
|
||||||
|
os.remove(os.path.join(
|
||||||
|
PROJECT_DIRECTORY, filename
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
# IN PROGRESS
|
# IN PROGRESS
|
||||||
# def copy_doc_files(project_directory):
|
# def copy_doc_files(project_directory):
|
||||||
# cookiecutters_dir = DEFAULT_CONFIG['cookiecutters_dir']
|
# cookiecutters_dir = DEFAULT_CONFIG['cookiecutters_dir']
|
||||||
|
@ -258,5 +290,10 @@ if '{{ cookiecutter.use_lets_encrypt }}'.lower() == 'y' and '{{ cookiecutter.use
|
||||||
if '{{ cookiecutter.open_source_license}}' != 'GPLv3':
|
if '{{ cookiecutter.open_source_license}}' != 'GPLv3':
|
||||||
remove_copying_files()
|
remove_copying_files()
|
||||||
|
|
||||||
# 4. Copy files from /docs/ to {{ cookiecutter.project_slug }}/docs/
|
# 12. Remove Elastic Beanstalk files
|
||||||
# copy_doc_files(PROJECT_DIRECTORY)
|
if '{{ cookiecutter.use_elasticbeanstalk_experimental }}'.lower() != 'y':
|
||||||
|
remove_elasticbeanstalk()
|
||||||
|
|
||||||
|
# 13. Remove files conventional to opensource projects only.
|
||||||
|
if '{{ cookiecutter.open_source_license }}' == 'Not open source':
|
||||||
|
remove_open_source_files()
|
|
@ -3,4 +3,29 @@ project_slug = '{{ cookiecutter.project_slug }}'
|
||||||
if hasattr(project_slug, 'isidentifier'):
|
if hasattr(project_slug, 'isidentifier'):
|
||||||
assert project_slug.isidentifier(), 'Project slug should be valid Python identifier!'
|
assert project_slug.isidentifier(), 'Project slug should be valid Python identifier!'
|
||||||
|
|
||||||
|
elasticbeanstalk = '{{ cookiecutter.use_elasticbeanstalk_experimental }}'.lower()
|
||||||
|
heroku = '{{ cookiecutter.use_heroku }}'.lower()
|
||||||
|
docker = '{{ cookiecutter.use_docker }}'.lower()
|
||||||
|
|
||||||
|
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':
|
||||||
|
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', ''])
|
||||||
|
choice = raw_input().lower()
|
||||||
|
if choice in no_options:
|
||||||
|
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 == ''])))
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
cookiecutter==1.4.0
|
cookiecutter==1.5.1
|
||||||
flake8==3.0.4 # pyup: != 2.6.0
|
flake8==3.3.0 # pyup: != 2.6.0
|
||||||
sh==1.11
|
sh==1.12.13
|
||||||
binaryornot==0.4.0
|
binaryornot==0.4.3
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
pytest==3.0.2
|
pytest==3.0.7
|
||||||
pep8==1.7.0
|
pep8==1.7.0
|
||||||
pyflakes==1.3.0
|
pyflakes==1.5.0
|
||||||
tox==2.3.1
|
tox==2.7.0
|
||||||
pytest-cookies==0.2.0
|
pytest-cookies==0.2.0
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
# These requirements prevented an upgrade to Django 1.10.
|
# These requirements prevented an upgrade to Django 1.10.
|
||||||
django-coverage-plugin==1.3.1
|
django-coverage-plugin==1.5.0
|
||||||
|
django-autoslug==1.9.3
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
[pytest]
|
[tool:pytest]
|
||||||
python_paths = .
|
python_paths = .
|
||||||
norecursedirs = .tox .git */migrations/* */static/* docs venv */{{cookiecutter.project_slug}}/*
|
norecursedirs = .tox .git */migrations/* */static/* docs venv */{{cookiecutter.project_slug}}/*
|
||||||
|
|
6
setup.py
6
setup.py
|
@ -10,7 +10,7 @@ except ImportError:
|
||||||
|
|
||||||
# Our version ALWAYS matches the version of Django we support
|
# Our version ALWAYS matches the version of Django we support
|
||||||
# If Django has a new release, we branch, tag, then update this setting after the tag.
|
# If Django has a new release, we branch, tag, then update this setting after the tag.
|
||||||
version = '1.9.9-04'
|
version = '1.10.7'
|
||||||
|
|
||||||
if sys.argv[-1] == 'tag':
|
if sys.argv[-1] == 'tag':
|
||||||
os.system('git tag -a %s -m "version %s"' % (version, version))
|
os.system('git tag -a %s -m "version %s"' % (version, version))
|
||||||
|
@ -34,13 +34,11 @@ setup(
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 4 - Beta',
|
'Development Status :: 4 - Beta',
|
||||||
'Environment :: Console',
|
'Environment :: Console',
|
||||||
'Framework :: Django :: 1.9',
|
'Framework :: Django :: 1.10',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'Natural Language :: English',
|
'Natural Language :: English',
|
||||||
'License :: OSI Approved :: BSD License',
|
'License :: OSI Approved :: BSD License',
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 2',
|
|
||||||
'Programming Language :: Python :: 2.7',
|
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3.4',
|
'Programming Language :: Python :: 3.4',
|
||||||
'Programming Language :: Python :: 3.5',
|
'Programming Language :: Python :: 3.5',
|
||||||
|
|
2
tests/test_cookiecutter_generation.py
Normal file → Executable file
2
tests/test_cookiecutter_generation.py
Normal file → Executable file
|
@ -1,5 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sh
|
import sh
|
||||||
|
|
5
tests/test_docker.sh
Normal file → Executable file
5
tests/test_docker.sh
Normal file → Executable file
|
@ -11,8 +11,11 @@ mkdir -p .cache/docker
|
||||||
cd .cache/docker
|
cd .cache/docker
|
||||||
|
|
||||||
# create the project using the default settings in cookiecutter.json
|
# create the project using the default settings in cookiecutter.json
|
||||||
cookiecutter ../../ --no-input --overwrite-if-exists
|
cookiecutter ../../ --no-input --overwrite-if-exists use_docker=y js_task_runner=None
|
||||||
cd project_name
|
cd project_name
|
||||||
|
|
||||||
# run the project's tests
|
# run the project's tests
|
||||||
docker-compose -f dev.yml run django python manage.py test
|
docker-compose -f dev.yml run django python manage.py test
|
||||||
|
|
||||||
|
# return non-zero status code if there are migrations that have not been created
|
||||||
|
docker-compose -f dev.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; }
|
||||||
|
|
2
tox.ini
2
tox.ini
|
@ -1,6 +1,6 @@
|
||||||
[tox]
|
[tox]
|
||||||
skipsdist = true
|
skipsdist = true
|
||||||
envlist = py27,py34,py35
|
envlist = py34,py35
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
passenv = LC_ALL, LANG, HOME
|
passenv = LC_ALL, LANG, HOME
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
packages:
|
||||||
|
yum:
|
||||||
|
git: []
|
||||||
|
postgresql94-devel: []
|
||||||
|
libjpeg-turbo-devel: []
|
|
@ -0,0 +1,46 @@
|
||||||
|
#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"
|
|
@ -0,0 +1,6 @@
|
||||||
|
option_settings:
|
||||||
|
"aws:elasticbeanstalk:customoption":
|
||||||
|
CacheNodeType : cache.t2.micro
|
||||||
|
NumCacheNodes : 1
|
||||||
|
Engine : redis
|
||||||
|
CachePort : 6379
|
17
{{cookiecutter.project_slug}}/.ebextensions/40_python.config
Normal file
17
{{cookiecutter.project_slug}}/.ebextensions/40_python.config
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
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/"
|
|
@ -0,0 +1,3 @@
|
||||||
|
container_commands:
|
||||||
|
01_setup_apache:
|
||||||
|
command: "cp .ebextensions/enable_mod_deflate.conf /etc/httpd/conf.d/enable_mod_deflate.conf"
|
|
@ -0,0 +1,25 @@
|
||||||
|
# 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>
|
5
{{cookiecutter.project_slug}}/.gitignore
vendored
5
{{cookiecutter.project_slug}}/.gitignore
vendored
|
@ -75,6 +75,7 @@ node_modules/
|
||||||
mailhog
|
mailhog
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if cookiecutter.use_compressor == 'y' %}
|
|
||||||
staticfiles/
|
staticfiles/
|
||||||
{% endif %}
|
|
||||||
|
.cache/
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<option name="PARENT_ENVS" value="true" />
|
<option name="PARENT_ENVS" value="true" />
|
||||||
<envs>
|
<envs>
|
||||||
<env name="PYTHONUNBUFFERED" value="1" />
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.local" />
|
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.test" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="SDK_HOME" value="docker-compose://$PROJECT_DIR$/dev.yml:pycharm/python" />
|
<option name="SDK_HOME" value="docker-compose://$PROJECT_DIR$/dev.yml:pycharm/python" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<option name="PARENT_ENVS" value="true" />
|
<option name="PARENT_ENVS" value="true" />
|
||||||
<envs>
|
<envs>
|
||||||
<env name="PYTHONUNBUFFERED" value="1" />
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.local" />
|
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.test" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="SDK_HOME" value="docker-compose://$PROJECT_DIR$/dev.yml:pycharm/python" />
|
<option name="SDK_HOME" value="docker-compose://$PROJECT_DIR$/dev.yml:pycharm/python" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<option name="PARENT_ENVS" value="true" />
|
<option name="PARENT_ENVS" value="true" />
|
||||||
<envs>
|
<envs>
|
||||||
<env name="PYTHONUNBUFFERED" value="1" />
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.local" />
|
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.test" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="SDK_HOME" value="docker-compose://$PROJECT_DIR$/dev.yml:pycharm/python" />
|
<option name="SDK_HOME" value="docker-compose://$PROJECT_DIR$/dev.yml:pycharm/python" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<option name="PARENT_ENVS" value="true" />
|
<option name="PARENT_ENVS" value="true" />
|
||||||
<envs>
|
<envs>
|
||||||
<env name="PYTHONUNBUFFERED" value="1" />
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.local" />
|
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.test" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="SDK_HOME" value="docker-compose://$PROJECT_DIR$/dev.yml:pycharm/python" />
|
<option name="SDK_HOME" value="docker-compose://$PROJECT_DIR$/dev.yml:pycharm/python" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<option name="PARENT_ENVS" value="true" />
|
<option name="PARENT_ENVS" value="true" />
|
||||||
<envs>
|
<envs>
|
||||||
<env name="PYTHONUNBUFFERED" value="1" />
|
<env name="PYTHONUNBUFFERED" value="1" />
|
||||||
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.local" />
|
<env name="DJANGO_SETTINGS_MODULE" value="config.settings.test" />
|
||||||
</envs>
|
</envs>
|
||||||
<option name="SDK_HOME" value="docker-compose://$PROJECT_DIR$/dev.yml:pycharm/python" />
|
<option name="SDK_HOME" value="docker-compose://$PROJECT_DIR$/dev.yml:pycharm/python" />
|
||||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
|
|
@ -8,8 +8,4 @@ before_install:
|
||||||
- sudo apt-get install -qq libsqlite3-dev libxml2 libxml2-dev libssl-dev libbz2-dev wget curl llvm
|
- sudo apt-get install -qq libsqlite3-dev libxml2 libxml2-dev libssl-dev libbz2-dev wget curl llvm
|
||||||
language: python
|
language: python
|
||||||
python:
|
python:
|
||||||
{% if cookiecutter.use_python3 == 'y' -%}
|
|
||||||
- "3.5"
|
- "3.5"
|
||||||
{% else %}
|
|
||||||
- "2.7"
|
|
||||||
{%- endif %}
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ The email server will exit when you exit the Grunt task on the CLI with Ctrl+C.
|
||||||
Sentry
|
Sentry
|
||||||
^^^^^^
|
^^^^^^
|
||||||
|
|
||||||
Sentry is an error logging aggregator service. You can sign up for a free account at https://getsentry.com/signup/?code=cookiecutter or download and host it yourself.
|
Sentry is an error logging aggregator service. You can sign up for a free account at https://sentry.io/signup/?code=cookiecutter or download and host it yourself.
|
||||||
The system is setup with reasonable defaults, including 404 logging and integration with the WSGI application.
|
The system is setup with reasonable defaults, including 404 logging and integration with the WSGI application.
|
||||||
|
|
||||||
You must set the DSN url in production.
|
You must set the DSN url in production.
|
||||||
|
@ -117,19 +117,16 @@ Deployment
|
||||||
----------
|
----------
|
||||||
|
|
||||||
The following details how to deploy this application.
|
The following details how to deploy this application.
|
||||||
{% if cookiecutter.use_heroku == "y" %}
|
{% if cookiecutter.use_heroku.lower() == "y" %}
|
||||||
|
|
||||||
Heroku
|
Heroku
|
||||||
^^^^^^
|
^^^^^^
|
||||||
|
|
||||||
.. image:: https://www.herokucdn.com/deploy/button.png
|
|
||||||
:target: https://heroku.com/deploy
|
|
||||||
|
|
||||||
See detailed `cookiecutter-django Heroku documentation`_.
|
See detailed `cookiecutter-django Heroku documentation`_.
|
||||||
|
|
||||||
.. _`cookiecutter-django Heroku documentation`: http://cookiecutter-django.readthedocs.io/en/latest/deployment-on-heroku.html
|
.. _`cookiecutter-django Heroku documentation`: http://cookiecutter-django.readthedocs.io/en/latest/deployment-on-heroku.html
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if cookiecutter.use_docker == "y" %}
|
{% if cookiecutter.use_docker.lower() == "y" %}
|
||||||
|
|
||||||
Docker
|
Docker
|
||||||
^^^^^^
|
^^^^^^
|
||||||
|
@ -138,3 +135,13 @@ See detailed `cookiecutter-django Docker documentation`_.
|
||||||
|
|
||||||
.. _`cookiecutter-django Docker documentation`: http://cookiecutter-django.readthedocs.io/en/latest/deployment-with-docker.html
|
.. _`cookiecutter-django Docker documentation`: http://cookiecutter-django.readthedocs.io/en/latest/deployment-with-docker.html
|
||||||
{% endif %}
|
{% 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 %}
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
{
|
|
||||||
"name": "{{cookiecutter.project_slug}}",
|
|
||||||
"description": "{{cookiecutter.description}}",
|
|
||||||
"env": {
|
|
||||||
"BUILDPACK_URL": "https://github.com/heroku/heroku-buildpack-python",
|
|
||||||
"DJANGO_SETTINGS_MODULE": "config.settings.production",
|
|
||||||
"DJANGO_SECRET_KEY": {
|
|
||||||
"description": "A secret key for verifying the integrity of signed cookies.",
|
|
||||||
"generator": "secret"
|
|
||||||
},
|
|
||||||
"DJANGO_ALLOWED_HOSTS": {
|
|
||||||
"description": "Comma-separated list of hosts",
|
|
||||||
"value": ".herokuapp.com"
|
|
||||||
},
|
|
||||||
"DJANGO_ADMIN_URL": {
|
|
||||||
"description": "A secret URL for the Django admin",
|
|
||||||
"generator": "secret"
|
|
||||||
},
|
|
||||||
"DJANGO_AWS_ACCESS_KEY_ID": "",
|
|
||||||
"DJANGO_AWS_SECRET_ACCESS_KEY": "",
|
|
||||||
"DJANGO_AWS_STORAGE_BUCKET_NAME": "",
|
|
||||||
"DJANGO_MAILGUN_SERVER_NAME": "",
|
|
||||||
"DJANGO_MAILGUN_API_KEY": ""{% if cookiecutter.use_sentry_for_error_reporting == "y" -%},
|
|
||||||
"DJANGO_SENTRY_DSN": ""{%- endif %}
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"postdeploy": "python manage.py migrate"
|
|
||||||
},
|
|
||||||
"addons": [
|
|
||||||
{
|
|
||||||
"plan": "heroku-postgresql:hobby-dev",
|
|
||||||
"options": {
|
|
||||||
"version": "{{ cookiecutter.postgresql_version }}"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"heroku-redis:hobby-dev",
|
|
||||||
"mailgun"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,8 +1,4 @@
|
||||||
{% if cookiecutter.use_python3 == 'y' -%}
|
|
||||||
FROM python:3.5
|
FROM python:3.5
|
||||||
{% else %}
|
|
||||||
FROM python:2.7
|
|
||||||
{%- endif %}
|
|
||||||
ENV PYTHONUNBUFFERED 1
|
ENV PYTHONUNBUFFERED 1
|
||||||
|
|
||||||
# Requirements have to be pulled and installed here, otherwise caching won't work
|
# Requirements have to be pulled and installed here, otherwise caching won't work
|
||||||
|
@ -12,9 +8,6 @@ RUN pip install -r /requirements/production.txt \
|
||||||
&& groupadd -r django \
|
&& groupadd -r django \
|
||||||
&& useradd -r -g django django
|
&& useradd -r -g django django
|
||||||
|
|
||||||
COPY . /app
|
|
||||||
RUN chown -R django /app
|
|
||||||
|
|
||||||
COPY ./compose/django/gunicorn.sh /gunicorn.sh
|
COPY ./compose/django/gunicorn.sh /gunicorn.sh
|
||||||
COPY ./compose/django/entrypoint.sh /entrypoint.sh
|
COPY ./compose/django/entrypoint.sh /entrypoint.sh
|
||||||
RUN sed -i 's/\r//' /entrypoint.sh \
|
RUN sed -i 's/\r//' /entrypoint.sh \
|
||||||
|
@ -24,6 +17,11 @@ RUN sed -i 's/\r//' /entrypoint.sh \
|
||||||
&& chmod +x /gunicorn.sh \
|
&& chmod +x /gunicorn.sh \
|
||||||
&& chown django /gunicorn.sh
|
&& chown django /gunicorn.sh
|
||||||
|
|
||||||
|
COPY . /app
|
||||||
|
|
||||||
|
RUN chown -R django /app
|
||||||
|
USER django
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
{% if cookiecutter.use_python3 == 'y' -%}
|
|
||||||
FROM python:3.5
|
FROM python:3.5
|
||||||
{% else %}
|
|
||||||
FROM python:2.7
|
|
||||||
{%- endif %}
|
|
||||||
ENV PYTHONUNBUFFERED 1
|
ENV PYTHONUNBUFFERED 1
|
||||||
|
|
||||||
# Requirements have to be pulled and installed here, otherwise caching won't work
|
# Requirements have to be pulled and installed here, otherwise caching won't work
|
||||||
|
|
|
@ -11,7 +11,7 @@ events {
|
||||||
|
|
||||||
http {
|
http {
|
||||||
|
|
||||||
include /etc/nginx/mime.types;
|
include /etc/nginx/mime.types;
|
||||||
default_type application/octet-stream;
|
default_type application/octet-stream;
|
||||||
|
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
|
@ -32,57 +32,57 @@ http {
|
||||||
upstream app {
|
upstream app {
|
||||||
server django:5000;
|
server django:5000;
|
||||||
}
|
}
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name ___my.example.com___ www.___my.example.com___;
|
server_name ___my.example.com___ www.___my.example.com___;
|
||||||
|
|
||||||
location /.well-known/acme-challenge {
|
location /.well-known/acme-challenge {
|
||||||
# Since the certbot container isn't up constantly, need to resolve ip dynamically using docker's dns
|
# Since the certbot container isn't up constantly, need to resolve ip dynamically using docker's dns
|
||||||
resolver ___NAMESERVER___;
|
resolver ___NAMESERVER___;
|
||||||
set $certbot_addr_port certbot:80;
|
set $certbot_addr_port certbot:80;
|
||||||
proxy_pass http://$certbot_addr_port;
|
proxy_pass http://$certbot_addr_port;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
return 301 https://$server_name$request_uri;
|
return 301 https://$server_name$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 443;
|
listen 443;
|
||||||
server_name ___my.example.com___ www.___my.example.com___;
|
server_name ___my.example.com___ www.___my.example.com___;
|
||||||
|
|
||||||
ssl on;
|
ssl on;
|
||||||
ssl_certificate /etc/letsencrypt/live/___my.example.com___/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/___my.example.com___/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/___my.example.com___/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/___my.example.com___/privkey.pem;
|
||||||
ssl_session_timeout 5m;
|
ssl_session_timeout 5m;
|
||||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||||
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
|
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
|
||||||
ssl_prefer_server_ciphers on;
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
ssl_session_cache shared:SSL:10m;
|
ssl_session_cache shared:SSL:10m;
|
||||||
ssl_dhparam /etc/ssl/private/dhparams.pem;
|
ssl_dhparam /etc/ssl/private/dhparams.pem;
|
||||||
|
|
||||||
location /.well-known/acme-challenge {
|
location /.well-known/acme-challenge {
|
||||||
resolver ___NAMESERVER___;
|
resolver ___NAMESERVER___;
|
||||||
set $certbot_addr_port certbot:443;
|
set $certbot_addr_port certbot:443;
|
||||||
proxy_pass http://$certbot_addr_port;
|
proxy_pass http://$certbot_addr_port;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
proxy_set_header X-Forwarded-Proto https;
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
# checks for static file, if not found proxy to app
|
# checks for static file, if not found proxy to app
|
||||||
try_files $uri @proxy_to_app;
|
try_files $uri @proxy_to_app;
|
||||||
}
|
}
|
||||||
|
|
||||||
# cookiecutter-django app
|
# cookiecutter-django app
|
||||||
location @proxy_to_app {
|
location @proxy_to_app {
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_redirect off;
|
proxy_redirect off;
|
||||||
|
@ -91,6 +91,6 @@ http {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
"""
|
||||||
Django settings for {{cookiecutter.project_name}} project.
|
Django settings for {{cookiecutter.project_name}} project.
|
||||||
|
|
||||||
|
@ -8,18 +7,29 @@ https://docs.djangoproject.com/en/dev/topics/settings/
|
||||||
For the full list of settings and their values, see
|
For the full list of settings and their values, see
|
||||||
https://docs.djangoproject.com/en/dev/ref/settings/
|
https://docs.djangoproject.com/en/dev/ref/settings/
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, unicode_literals
|
|
||||||
|
|
||||||
import environ
|
import environ
|
||||||
|
|
||||||
ROOT_DIR = environ.Path(__file__) - 3 # ({{ cookiecutter.project_slug }}/config/settings/common.py - 3 = {{ cookiecutter.project_slug }}/)
|
ROOT_DIR = environ.Path(__file__) - 3 # ({{ cookiecutter.project_slug }}/config/settings/base.py - 3 = {{ cookiecutter.project_slug }}/)
|
||||||
APPS_DIR = ROOT_DIR.path('{{ cookiecutter.project_slug }}')
|
APPS_DIR = ROOT_DIR.path('{{ cookiecutter.project_slug }}')
|
||||||
|
|
||||||
|
# Load operating system environment variables and then prepare to use them
|
||||||
env = environ.Env()
|
env = environ.Env()
|
||||||
|
|
||||||
|
# .env file, should load only in development environment
|
||||||
|
READ_DOT_ENV_FILE = env.bool('DJANGO_READ_DOT_ENV_FILE', default=False)
|
||||||
|
|
||||||
|
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')
|
||||||
|
|
||||||
# APP CONFIGURATION
|
# APP CONFIGURATION
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
DJANGO_APPS = (
|
DJANGO_APPS = [
|
||||||
# Default Django apps:
|
# Default Django apps:
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
|
@ -33,27 +43,27 @@ DJANGO_APPS = (
|
||||||
|
|
||||||
# Admin
|
# Admin
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
)
|
]
|
||||||
THIRD_PARTY_APPS = (
|
THIRD_PARTY_APPS = [
|
||||||
'crispy_forms', # Form layouts
|
'crispy_forms', # Form layouts
|
||||||
'allauth', # registration
|
'allauth', # registration
|
||||||
'allauth.account', # registration
|
'allauth.account', # registration
|
||||||
'allauth.socialaccount', # registration
|
'allauth.socialaccount', # registration
|
||||||
)
|
]
|
||||||
|
|
||||||
# Apps specific for this project go here.
|
# Apps specific for this project go here.
|
||||||
LOCAL_APPS = (
|
LOCAL_APPS = [
|
||||||
# custom users app
|
# custom users app
|
||||||
'{{ cookiecutter.project_slug }}.users.apps.UsersConfig',
|
'{{ cookiecutter.project_slug }}.users.apps.UsersConfig',
|
||||||
# Your stuff: custom apps go here
|
# Your stuff: custom apps go here
|
||||||
)
|
]
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
|
# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
|
||||||
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
|
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
|
||||||
|
|
||||||
# MIDDLEWARE CONFIGURATION
|
# MIDDLEWARE CONFIGURATION
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
MIDDLEWARE_CLASSES = (
|
MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
@ -61,7 +71,7 @@ MIDDLEWARE_CLASSES = (
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
)
|
]
|
||||||
|
|
||||||
# MIGRATIONS CONFIGURATION
|
# MIGRATIONS CONFIGURATION
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -88,9 +98,9 @@ EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND', default='django.core.mail.backends.s
|
||||||
# MANAGER CONFIGURATION
|
# MANAGER CONFIGURATION
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#admins
|
# See: https://docs.djangoproject.com/en/dev/ref/settings/#admins
|
||||||
ADMINS = (
|
ADMINS = [
|
||||||
("""{{cookiecutter.author_name}}""", '{{cookiecutter.email}}'),
|
("""{{cookiecutter.author_name}}""", '{{cookiecutter.email}}'),
|
||||||
)
|
]
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#managers
|
# See: https://docs.djangoproject.com/en/dev/ref/settings/#managers
|
||||||
MANAGERS = ADMINS
|
MANAGERS = ADMINS
|
||||||
|
@ -175,15 +185,15 @@ STATIC_ROOT = str(ROOT_DIR('staticfiles'))
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
|
# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
|
||||||
STATICFILES_DIRS = (
|
STATICFILES_DIRS = [
|
||||||
str(APPS_DIR.path('static')),
|
str(APPS_DIR.path('static')),
|
||||||
)
|
]
|
||||||
|
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
|
# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
|
||||||
STATICFILES_FINDERS = (
|
STATICFILES_FINDERS = [
|
||||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||||
)
|
]
|
||||||
|
|
||||||
# MEDIA CONFIGURATION
|
# MEDIA CONFIGURATION
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -200,12 +210,42 @@ ROOT_URLCONF = 'config.urls'
|
||||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
|
# See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
|
||||||
WSGI_APPLICATION = 'config.wsgi.application'
|
WSGI_APPLICATION = 'config.wsgi.application'
|
||||||
|
|
||||||
|
# PASSWORD STORAGE SETTINGS
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# See https://docs.djangoproject.com/en/dev/topics/auth/passwords/#using-argon2-with-django
|
||||||
|
PASSWORD_HASHERS = [
|
||||||
|
'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',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
# AUTHENTICATION CONFIGURATION
|
# AUTHENTICATION CONFIGURATION
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
AUTHENTICATION_BACKENDS = (
|
AUTHENTICATION_BACKENDS = [
|
||||||
'django.contrib.auth.backends.ModelBackend',
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
'allauth.account.auth_backends.AuthenticationBackend',
|
'allauth.account.auth_backends.AuthenticationBackend',
|
||||||
)
|
]
|
||||||
|
|
||||||
# Some really nice defaults
|
# Some really nice defaults
|
||||||
ACCOUNT_AUTHENTICATION_METHOD = 'username'
|
ACCOUNT_AUTHENTICATION_METHOD = 'username'
|
||||||
|
@ -226,22 +266,20 @@ LOGIN_URL = 'account_login'
|
||||||
AUTOSLUG_SLUGIFY_FUNCTION = 'slugify.slugify'
|
AUTOSLUG_SLUGIFY_FUNCTION = 'slugify.slugify'
|
||||||
{% if cookiecutter.use_celery == 'y' %}
|
{% if cookiecutter.use_celery == 'y' %}
|
||||||
########## CELERY
|
########## CELERY
|
||||||
INSTALLED_APPS += ('{{cookiecutter.project_slug}}.taskapp.celery.CeleryConfig',)
|
INSTALLED_APPS += ['{{cookiecutter.project_slug}}.taskapp.celery.CeleryConfig']
|
||||||
# if you are not using the django database broker (e.g. rabbitmq, redis, memcached), you can remove the next line.
|
CELERY_BROKER_URL = env('CELERY_BROKER_URL', default='django://')
|
||||||
INSTALLED_APPS += ('kombu.transport.django',)
|
if CELERY_BROKER_URL == 'django://':
|
||||||
BROKER_URL = env('CELERY_BROKER_URL', default='django://')
|
|
||||||
if BROKER_URL == 'django://':
|
|
||||||
CELERY_RESULT_BACKEND = 'redis://'
|
CELERY_RESULT_BACKEND = 'redis://'
|
||||||
else:
|
else:
|
||||||
CELERY_RESULT_BACKEND = BROKER_URL
|
CELERY_RESULT_BACKEND = CELERY_BROKER_URL
|
||||||
########## END CELERY
|
########## END CELERY
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{%- if cookiecutter.use_compressor == 'y'-%}
|
{%- if cookiecutter.use_compressor == 'y'-%}
|
||||||
# django-compressor
|
# django-compressor
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
INSTALLED_APPS += ("compressor", )
|
INSTALLED_APPS += ['compressor']
|
||||||
STATICFILES_FINDERS += ("compressor.finders.CompressorFinder", )
|
STATICFILES_FINDERS += ['compressor.finders.CompressorFinder']
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
# Location of root django.contrib.admin URL, use {% raw %}{% url 'admin:index' %}{% endraw %}
|
# Location of root django.contrib.admin URL, use {% raw %}{% url 'admin:index' %}{% endraw %}
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
"""
|
||||||
Local settings
|
Local settings
|
||||||
|
|
||||||
|
@ -12,9 +11,7 @@ Local settings
|
||||||
- Add django-extensions as app
|
- Add django-extensions as app
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import socket
|
from .base import * # noqa
|
||||||
import os
|
|
||||||
from .common import * # noqa
|
|
||||||
|
|
||||||
# DEBUG
|
# DEBUG
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -32,7 +29,7 @@ SECRET_KEY = env('DJANGO_SECRET_KEY', default='CHANGEME!!!')
|
||||||
|
|
||||||
EMAIL_PORT = 1025
|
EMAIL_PORT = 1025
|
||||||
{% if cookiecutter.use_mailhog == 'y' and cookiecutter.use_docker == 'y' %}
|
{% if cookiecutter.use_mailhog == 'y' and cookiecutter.use_docker == 'y' %}
|
||||||
EMAIL_HOST = env("EMAIL_HOST", default='mailhog')
|
EMAIL_HOST = env('EMAIL_HOST', default='mailhog')
|
||||||
{% else %}
|
{% else %}
|
||||||
EMAIL_HOST = 'localhost'
|
EMAIL_HOST = 'localhost'
|
||||||
EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND',
|
EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND',
|
||||||
|
@ -50,15 +47,19 @@ CACHES = {
|
||||||
|
|
||||||
# django-debug-toolbar
|
# django-debug-toolbar
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',)
|
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware', ]
|
||||||
INSTALLED_APPS += ('debug_toolbar', )
|
INSTALLED_APPS += ['debug_toolbar', ]
|
||||||
|
|
||||||
INTERNAL_IPS = ['127.0.0.1', '10.0.2.2', ]
|
INTERNAL_IPS = ['127.0.0.1', '10.0.2.2', ]
|
||||||
|
{% if cookiecutter.use_docker == 'y' %}
|
||||||
|
{# [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
|
# tricks to have debug toolbar when developing with docker
|
||||||
if os.environ.get('USE_DOCKER') == 'yes':
|
if os.environ.get('USE_DOCKER') == 'yes':
|
||||||
ip = socket.gethostbyname(socket.gethostname())
|
ip = socket.gethostbyname(socket.gethostname())
|
||||||
INTERNAL_IPS += [ip[:-1] + "1"]
|
INTERNAL_IPS += [ip[:-1] + '1']
|
||||||
|
{% endif %}
|
||||||
DEBUG_TOOLBAR_CONFIG = {
|
DEBUG_TOOLBAR_CONFIG = {
|
||||||
'DISABLE_PANELS': [
|
'DISABLE_PANELS': [
|
||||||
'debug_toolbar.panels.redirects.RedirectsPanel',
|
'debug_toolbar.panels.redirects.RedirectsPanel',
|
||||||
|
@ -68,7 +69,7 @@ DEBUG_TOOLBAR_CONFIG = {
|
||||||
|
|
||||||
# django-extensions
|
# django-extensions
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
INSTALLED_APPS += ('django_extensions', )
|
INSTALLED_APPS += ['django_extensions', ]
|
||||||
|
|
||||||
# TESTING
|
# TESTING
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
"""
|
||||||
Production Configurations
|
Production Configurations
|
||||||
|
|
||||||
|
@ -12,15 +11,13 @@ Production Configurations
|
||||||
- Use opbeat for error reporting
|
- Use opbeat for error reporting
|
||||||
{% endif %}
|
{% endif %}
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from boto.s3.connection import OrdinaryCallingFormat
|
from boto.s3.connection import OrdinaryCallingFormat
|
||||||
from django.utils import six
|
|
||||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
{% if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
||||||
import logging
|
import logging
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
from .common import * # noqa
|
from .base import * # noqa
|
||||||
|
|
||||||
# SECRET CONFIGURATION
|
# SECRET CONFIGURATION
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -35,37 +32,35 @@ SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||||
|
|
||||||
{%- if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
{%- if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
||||||
# raven sentry client
|
# raven sentry client
|
||||||
# See https://docs.getsentry.com/hosted/clients/python/integrations/django/
|
# See https://docs.sentry.io/clients/python/integrations/django/
|
||||||
INSTALLED_APPS += ('raven.contrib.django.raven_compat', )
|
INSTALLED_APPS += ['raven.contrib.django.raven_compat', ]
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{%- if cookiecutter.use_whitenoise == 'y' %}
|
{%- if cookiecutter.use_whitenoise == 'y' %}
|
||||||
# Use Whitenoise to serve static files
|
# Use Whitenoise to serve static files
|
||||||
# See: https://whitenoise.readthedocs.io/
|
# See: https://whitenoise.readthedocs.io/
|
||||||
WHITENOISE_MIDDLEWARE = ('whitenoise.middleware.WhiteNoiseMiddleware', )
|
WHITENOISE_MIDDLEWARE = ['whitenoise.middleware.WhiteNoiseMiddleware', ]
|
||||||
MIDDLEWARE_CLASSES = WHITENOISE_MIDDLEWARE + MIDDLEWARE_CLASSES
|
MIDDLEWARE = WHITENOISE_MIDDLEWARE + MIDDLEWARE
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{%- if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
{%- if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
||||||
RAVEN_MIDDLEWARE = ('raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware', )
|
RAVEN_MIDDLEWARE = ['raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware']
|
||||||
MIDDLEWARE_CLASSES = RAVEN_MIDDLEWARE + MIDDLEWARE_CLASSES
|
MIDDLEWARE = RAVEN_MIDDLEWARE + MIDDLEWARE
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{%- if cookiecutter.use_opbeat == 'y' -%}
|
{%- if cookiecutter.use_opbeat == 'y' -%}
|
||||||
# opbeat integration
|
# opbeat integration
|
||||||
# See https://opbeat.com/languages/django/
|
# See https://opbeat.com/languages/django/
|
||||||
INSTALLED_APPS += ('opbeat.contrib.django',)
|
INSTALLED_APPS += ['opbeat.contrib.django', ]
|
||||||
OPBEAT = {
|
OPBEAT = {
|
||||||
'ORGANIZATION_ID': env('DJANGO_OPBEAT_ORGANIZATION_ID'),
|
'ORGANIZATION_ID': env('DJANGO_OPBEAT_ORGANIZATION_ID'),
|
||||||
'APP_ID': env('DJANGO_OPBEAT_APP_ID'),
|
'APP_ID': env('DJANGO_OPBEAT_APP_ID'),
|
||||||
'SECRET_TOKEN': env('DJANGO_OPBEAT_SECRET_TOKEN')
|
'SECRET_TOKEN': env('DJANGO_OPBEAT_SECRET_TOKEN')
|
||||||
}
|
}
|
||||||
MIDDLEWARE_CLASSES = (
|
MIDDLEWARE = ['opbeat.contrib.django.middleware.OpbeatAPMMiddleware', ] + MIDDLEWARE
|
||||||
'opbeat.contrib.django.middleware.OpbeatAPMMiddleware',
|
|
||||||
) + MIDDLEWARE_CLASSES
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
# SECURITY CONFIGURATION
|
# SECURITY CONFIGURATION
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# See https://docs.djangoproject.com/en/1.9/ref/middleware/#module-django.middleware.security
|
# See https://docs.djangoproject.com/en/dev/ref/middleware/#module-django.middleware.security
|
||||||
# and https://docs.djangoproject.com/ja/1.9/howto/deployment/checklist/#run-manage-py-check-deploy
|
# 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
|
# set this to 60 seconds and then to 518400 when you can prove it works
|
||||||
SECURE_HSTS_SECONDS = 60
|
SECURE_HSTS_SECONDS = 60
|
||||||
|
@ -84,11 +79,11 @@ X_FRAME_OPTIONS = 'DENY'
|
||||||
# SITE CONFIGURATION
|
# SITE CONFIGURATION
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Hosts/domain names that are valid for this site
|
# Hosts/domain names that are valid for this site
|
||||||
# See https://docs.djangoproject.com/en/1.6/ref/settings/#allowed-hosts
|
# See https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
|
||||||
ALLOWED_HOSTS = env.list('DJANGO_ALLOWED_HOSTS', default=['{{cookiecutter.domain_name}}'])
|
ALLOWED_HOSTS = env.list('DJANGO_ALLOWED_HOSTS', default=['{{cookiecutter.domain_name}}', ])
|
||||||
# END SITE CONFIGURATION
|
# END SITE CONFIGURATION
|
||||||
|
|
||||||
INSTALLED_APPS += ('gunicorn', )
|
INSTALLED_APPS += ['gunicorn', ]
|
||||||
|
|
||||||
|
|
||||||
# STORAGE CONFIGURATION
|
# STORAGE CONFIGURATION
|
||||||
|
@ -96,9 +91,7 @@ INSTALLED_APPS += ('gunicorn', )
|
||||||
# Uploaded Media Files
|
# Uploaded Media Files
|
||||||
# ------------------------
|
# ------------------------
|
||||||
# See: http://django-storages.readthedocs.io/en/latest/index.html
|
# See: http://django-storages.readthedocs.io/en/latest/index.html
|
||||||
INSTALLED_APPS += (
|
INSTALLED_APPS += ['storages', ]
|
||||||
'storages',
|
|
||||||
)
|
|
||||||
|
|
||||||
AWS_ACCESS_KEY_ID = env('DJANGO_AWS_ACCESS_KEY_ID')
|
AWS_ACCESS_KEY_ID = env('DJANGO_AWS_ACCESS_KEY_ID')
|
||||||
AWS_SECRET_ACCESS_KEY = env('DJANGO_AWS_SECRET_ACCESS_KEY')
|
AWS_SECRET_ACCESS_KEY = env('DJANGO_AWS_SECRET_ACCESS_KEY')
|
||||||
|
@ -113,9 +106,9 @@ AWS_EXPIRY = 60 * 60 * 24 * 7
|
||||||
# TODO See: https://github.com/jschneier/django-storages/issues/47
|
# TODO See: https://github.com/jschneier/django-storages/issues/47
|
||||||
# Revert the following and use str after the above-mentioned bug is fixed in
|
# Revert the following and use str after the above-mentioned bug is fixed in
|
||||||
# either django-storage-redux or boto
|
# either django-storage-redux or boto
|
||||||
|
control = 'max-age=%d, s-maxage=%d, must-revalidate' % (AWS_EXPIRY, AWS_EXPIRY)
|
||||||
AWS_HEADERS = {
|
AWS_HEADERS = {
|
||||||
'Cache-Control': six.b('max-age=%d, s-maxage=%d, must-revalidate' % (
|
'Cache-Control': bytes(control, encoding='latin-1')
|
||||||
AWS_EXPIRY, AWS_EXPIRY))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# URL that handles the media served from MEDIA_ROOT, used for managing
|
# URL that handles the media served from MEDIA_ROOT, used for managing
|
||||||
|
@ -143,7 +136,7 @@ STATICFILES_STORAGE = 'config.settings.production.StaticRootS3BotoStorage'
|
||||||
# For Django 1.7+, 'collectfast' should come before
|
# For Django 1.7+, 'collectfast' should come before
|
||||||
# 'django.contrib.staticfiles'
|
# 'django.contrib.staticfiles'
|
||||||
AWS_PRELOAD_METADATA = True
|
AWS_PRELOAD_METADATA = True
|
||||||
INSTALLED_APPS = ('collectfast', ) + INSTALLED_APPS
|
INSTALLED_APPS = ['collectfast', ] + INSTALLED_APPS
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{% if cookiecutter.use_compressor == 'y'-%}
|
{% if cookiecutter.use_compressor == 'y'-%}
|
||||||
# COMPRESSOR
|
# COMPRESSOR
|
||||||
|
@ -156,15 +149,16 @@ COMPRESS_ENABLED = env.bool('COMPRESS_ENABLED', default=True)
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
DEFAULT_FROM_EMAIL = env('DJANGO_DEFAULT_FROM_EMAIL',
|
DEFAULT_FROM_EMAIL = env('DJANGO_DEFAULT_FROM_EMAIL',
|
||||||
default='{{cookiecutter.project_name}} <noreply@{{cookiecutter.domain_name}}>')
|
default='{{cookiecutter.project_name}} <noreply@{{cookiecutter.domain_name}}>')
|
||||||
EMAIL_SUBJECT_PREFIX = env('DJANGO_EMAIL_SUBJECT_PREFIX', default='[{{cookiecutter.project_name}}] ')
|
EMAIL_SUBJECT_PREFIX = env('DJANGO_EMAIL_SUBJECT_PREFIX', default='[{{cookiecutter.project_name}}]')
|
||||||
SERVER_EMAIL = env('DJANGO_SERVER_EMAIL', default=DEFAULT_FROM_EMAIL)
|
SERVER_EMAIL = env('DJANGO_SERVER_EMAIL', default=DEFAULT_FROM_EMAIL)
|
||||||
|
|
||||||
# Anymail with Mailgun
|
# Anymail with Mailgun
|
||||||
INSTALLED_APPS += ("anymail", )
|
INSTALLED_APPS += ['anymail', ]
|
||||||
ANYMAIL = {
|
ANYMAIL = {
|
||||||
"MAILGUN_API_KEY": env('DJANGO_MAILGUN_API_KEY'),
|
'MAILGUN_API_KEY': env('DJANGO_MAILGUN_API_KEY'),
|
||||||
|
'MAILGUN_SENDER_DOMAIN': env('MAILGUN_SENDER_DOMAIN')
|
||||||
}
|
}
|
||||||
EMAIL_BACKEND = "anymail.backends.mailgun.MailgunBackend"
|
EMAIL_BACKEND = 'anymail.backends.mailgun.MailgunBackend'
|
||||||
|
|
||||||
# TEMPLATE CONFIGURATION
|
# TEMPLATE CONFIGURATION
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -177,16 +171,39 @@ TEMPLATES[0]['OPTIONS']['loaders'] = [
|
||||||
|
|
||||||
# DATABASE CONFIGURATION
|
# 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'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{% else %}
|
||||||
|
# Use the Heroku-style specification
|
||||||
# Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
|
# Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
|
||||||
DATABASES['default'] = env.db('DATABASE_URL')
|
DATABASES['default'] = env.db('DATABASE_URL')
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
# CACHING
|
# CACHING
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
{% 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
|
# Heroku URL does not pass the DB number, so we parse it in
|
||||||
CACHES = {
|
CACHES = {
|
||||||
'default': {
|
'default': {
|
||||||
'BACKEND': 'django_redis.cache.RedisCache',
|
'BACKEND': 'django_redis.cache.RedisCache',
|
||||||
'LOCATION': '{0}/{1}'.format(env('REDIS_URL', default='redis://127.0.0.1:6379'), 0),
|
'LOCATION': REDIS_LOCATION,
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
|
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
|
||||||
'IGNORE_EXCEPTIONS': True, # mimics memcache behavior.
|
'IGNORE_EXCEPTIONS': True, # mimics memcache behavior.
|
||||||
|
@ -204,7 +221,7 @@ LOGGING = {
|
||||||
'disable_existing_loggers': True,
|
'disable_existing_loggers': True,
|
||||||
'root': {
|
'root': {
|
||||||
'level': 'WARNING',
|
'level': 'WARNING',
|
||||||
'handlers': ['sentry'],
|
'handlers': ['sentry', ],
|
||||||
},
|
},
|
||||||
'formatters': {
|
'formatters': {
|
||||||
'verbose': {
|
'verbose': {
|
||||||
|
@ -226,22 +243,22 @@ LOGGING = {
|
||||||
'loggers': {
|
'loggers': {
|
||||||
'django.db.backends': {
|
'django.db.backends': {
|
||||||
'level': 'ERROR',
|
'level': 'ERROR',
|
||||||
'handlers': ['console'],
|
'handlers': ['console', ],
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
},
|
},
|
||||||
'raven': {
|
'raven': {
|
||||||
'level': 'DEBUG',
|
'level': 'DEBUG',
|
||||||
'handlers': ['console'],
|
'handlers': ['console', ],
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
},
|
},
|
||||||
'sentry.errors': {
|
'sentry.errors': {
|
||||||
'level': 'DEBUG',
|
'level': 'DEBUG',
|
||||||
'handlers': ['console'],
|
'handlers': ['console', ],
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
},
|
},
|
||||||
'django.security.DisallowedHost': {
|
'django.security.DisallowedHost': {
|
||||||
'level': 'ERROR',
|
'level': 'ERROR',
|
||||||
'handlers': ['console', 'sentry'],
|
'handlers': ['console', 'sentry', ],
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -258,7 +275,7 @@ RAVEN_CONFIG = {
|
||||||
# A sample logging configuration. The only tangible logging
|
# A sample logging configuration. The only tangible logging
|
||||||
# performed by this configuration is to send an email to
|
# performed by this configuration is to send an email to
|
||||||
# the site admins on every HTTP 500 error when DEBUG=False.
|
# the site admins on every HTTP 500 error when DEBUG=False.
|
||||||
# See http://docs.djangoproject.com/en/dev/topics/logging for
|
# See https://docs.djangoproject.com/en/dev/topics/logging for
|
||||||
# more details on how to customize your logging configuration.
|
# more details on how to customize your logging configuration.
|
||||||
LOGGING = {
|
LOGGING = {
|
||||||
'version': 1,
|
'version': 1,
|
||||||
|
@ -277,7 +294,7 @@ LOGGING = {
|
||||||
'handlers': {
|
'handlers': {
|
||||||
'mail_admins': {
|
'mail_admins': {
|
||||||
'level': 'ERROR',
|
'level': 'ERROR',
|
||||||
'filters': ['require_debug_false'],
|
'filters': ['require_debug_false', ],
|
||||||
'class': 'django.utils.log.AdminEmailHandler'
|
'class': 'django.utils.log.AdminEmailHandler'
|
||||||
},
|
},
|
||||||
'console': {
|
'console': {
|
||||||
|
@ -288,13 +305,13 @@ LOGGING = {
|
||||||
},
|
},
|
||||||
'loggers': {
|
'loggers': {
|
||||||
'django.request': {
|
'django.request': {
|
||||||
'handlers': ['mail_admins'],
|
'handlers': ['mail_admins', ],
|
||||||
'level': 'ERROR',
|
'level': 'ERROR',
|
||||||
'propagate': True
|
'propagate': True
|
||||||
},
|
},
|
||||||
'django.security.DisallowedHost': {
|
'django.security.DisallowedHost': {
|
||||||
'level': 'ERROR',
|
'level': 'ERROR',
|
||||||
'handlers': ['console', 'mail_admins'],
|
'handlers': ['console', 'mail_admins', ],
|
||||||
'propagate': True
|
'propagate': True
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
'''
|
'''
|
||||||
Test settings
|
Test settings
|
||||||
|
|
||||||
- Used to run tests fast on the continuous integration server and locally
|
- Used to run tests fast on the continuous integration server and locally
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from .common import * # noqa
|
from .base import * # noqa
|
||||||
|
|
||||||
|
|
||||||
# DEBUG
|
# DEBUG
|
||||||
|
@ -47,16 +46,16 @@ TEST_RUNNER = 'django.test.runner.DiscoverRunner'
|
||||||
# PASSWORD HASHING
|
# PASSWORD HASHING
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Use fast password hasher so tests run faster
|
# Use fast password hasher so tests run faster
|
||||||
PASSWORD_HASHERS = (
|
PASSWORD_HASHERS = [
|
||||||
'django.contrib.auth.hashers.MD5PasswordHasher',
|
'django.contrib.auth.hashers.MD5PasswordHasher',
|
||||||
)
|
]
|
||||||
|
|
||||||
# TEMPLATE LOADERS
|
# TEMPLATE LOADERS
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Keep templates in memory so tests run faster
|
# Keep templates in memory so tests run faster
|
||||||
TEMPLATES[0]['OPTIONS']['loaders'] = [
|
TEMPLATES[0]['OPTIONS']['loaders'] = [
|
||||||
('django.template.loaders.cached.Loader', [
|
['django.template.loaders.cached.Loader', [
|
||||||
'django.template.loaders.filesystem.Loader',
|
'django.template.loaders.filesystem.Loader',
|
||||||
'django.template.loaders.app_directories.Loader',
|
'django.template.loaders.app_directories.Loader',
|
||||||
]),
|
], ],
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import include, url
|
from django.conf.urls import include, url
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
|
@ -13,7 +10,7 @@ urlpatterns = [
|
||||||
url(r'^about/$', TemplateView.as_view(template_name='pages/about.html'), name='about'),
|
url(r'^about/$', TemplateView.as_view(template_name='pages/about.html'), name='about'),
|
||||||
|
|
||||||
# Django Admin, use {% raw %}{% url 'admin:index' %}{% endraw %}
|
# Django Admin, use {% raw %}{% url 'admin:index' %}{% endraw %}
|
||||||
url(settings.ADMIN_URL, include(admin.site.urls)),
|
url(settings.ADMIN_URL, admin.site.urls),
|
||||||
|
|
||||||
# User management
|
# User management
|
||||||
url(r'^users/', include('{{ cookiecutter.project_slug }}.users.urls', namespace='users')),
|
url(r'^users/', include('{{ cookiecutter.project_slug }}.users.urls', namespace='users')),
|
||||||
|
@ -33,3 +30,8 @@ if settings.DEBUG:
|
||||||
url(r'^404/$', default_views.page_not_found, kwargs={'exception': Exception('Page not Found')}),
|
url(r'^404/$', default_views.page_not_found, kwargs={'exception': Exception('Page not Found')}),
|
||||||
url(r'^500/$', default_views.server_error),
|
url(r'^500/$', default_views.server_error),
|
||||||
]
|
]
|
||||||
|
if 'debug_toolbar' in settings.INSTALLED_APPS:
|
||||||
|
import debug_toolbar
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^__debug__/', include(debug_toolbar.urls)),
|
||||||
|
] + urlpatterns
|
||||||
|
|
|
@ -14,8 +14,15 @@ framework.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
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', '')
|
||||||
|
sys.path.append(os.path.join(app_path, '{{ cookiecutter.project_slug }}'))
|
||||||
|
|
||||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
{% if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
||||||
if os.environ.get('DJANGO_SETTINGS_MODULE') == 'config.settings.production':
|
if os.environ.get('DJANGO_SETTINGS_MODULE') == 'config.settings.production':
|
||||||
from raven.contrib.django.raven_compat.middleware.wsgi import Sentry
|
from raven.contrib.django.raven_compat.middleware.wsgi import Sentry
|
||||||
|
|
|
@ -19,7 +19,8 @@ services:
|
||||||
dockerfile: ./compose/django/Dockerfile-dev
|
dockerfile: ./compose/django/Dockerfile-dev
|
||||||
command: /start-dev.sh
|
command: /start-dev.sh
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres{% if cookiecutter.use_mailhog == 'y' %}
|
||||||
|
- mailhog{% endif %}
|
||||||
environment:
|
environment:
|
||||||
- POSTGRES_USER={{cookiecutter.project_slug}}
|
- POSTGRES_USER={{cookiecutter.project_slug}}
|
||||||
- USE_DOCKER=yes
|
- USE_DOCKER=yes
|
||||||
|
@ -27,11 +28,6 @@ services:
|
||||||
- .:/app
|
- .:/app
|
||||||
ports:
|
ports:
|
||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
links:
|
|
||||||
- postgres
|
|
||||||
{% if cookiecutter.use_mailhog == 'y' %}
|
|
||||||
- mailhog
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if cookiecutter.use_pycharm == 'y' %}
|
{% if cookiecutter.use_pycharm == 'y' %}
|
||||||
pycharm:
|
pycharm:
|
||||||
|
@ -44,8 +40,6 @@ services:
|
||||||
- POSTGRES_USER={{cookiecutter.project_slug}}
|
- POSTGRES_USER={{cookiecutter.project_slug}}
|
||||||
volumes:
|
volumes:
|
||||||
- .:/app
|
- .:/app
|
||||||
links:
|
|
||||||
- postgres
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if cookiecutter.use_mailhog == 'y' %}
|
{% if cookiecutter.use_mailhog == 'y' %}
|
||||||
|
|
|
@ -16,7 +16,6 @@ services:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: ./compose/django/Dockerfile
|
dockerfile: ./compose/django/Dockerfile
|
||||||
user: django
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
- redis
|
- redis
|
||||||
|
@ -57,13 +56,12 @@ services:
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:latest
|
image: redis:3.0
|
||||||
{% if cookiecutter.use_celery == 'y' %}
|
{% if cookiecutter.use_celery == 'y' %}
|
||||||
celeryworker:
|
celeryworker:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: ./compose/django/Dockerfile
|
dockerfile: ./compose/django/Dockerfile
|
||||||
user: django
|
|
||||||
env_file: .env
|
env_file: .env
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
|
@ -74,7 +72,6 @@ services:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: ./compose/django/Dockerfile
|
dockerfile: ./compose/django/Dockerfile
|
||||||
user: django
|
|
||||||
env_file: .env
|
env_file: .env
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# {{ cookiecutter.project_name }} documentation build configuration file, created by
|
# {{ cookiecutter.project_name }} documentation build configuration file, created by
|
||||||
# sphinx-quickstart.
|
# sphinx-quickstart.
|
||||||
#
|
#
|
||||||
|
@ -11,8 +9,6 @@
|
||||||
# All configuration values have a default; values that are commented out
|
# All configuration values have a default; values that are commented out
|
||||||
# serve to show the default.
|
# serve to show the default.
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ The Docker compose tool (previously known as `fig`_) makes linking these contain
|
||||||
...
|
...
|
||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
|
|
||||||
Each component of your application would get its own `Dockerfile`_. The rest of this example assumes you are using the `base postgres image`_ for your database. Your database settings in `config/common.py` might then look something like:
|
Each component of your application would get its own `Dockerfile`_. The rest of this example assumes you are using the `base postgres image`_ for your database. Your database settings in `config/base.py` might then look something like:
|
||||||
|
|
||||||
.. _Dockerfile: https://docs.docker.com/reference/builder/
|
.. _Dockerfile: https://docs.docker.com/reference/builder/
|
||||||
.. _base postgres image: https://registry.hub.docker.com/_/postgres/
|
.. _base postgres image: https://registry.hub.docker.com/_/postgres/
|
||||||
|
|
|
@ -14,7 +14,7 @@ This repository comes with already prepared "Run/Debug Configurations" for docke
|
||||||
|
|
||||||
.. image:: images/2.png
|
.. image:: images/2.png
|
||||||
|
|
||||||
But as you can see, at the beggining there is something wrong with them. They have red X on django icon, and they cannot be used, withot configuring remote python interpteter. To do that, you have to go to *Settings > Build, Execution, Deployment* first.
|
But as you can see, at the beggining there is something wrong with them. They have red X on django icon, and they cannot be used, without configuring remote python interpteter. To do that, you have to go to *Settings > Build, Execution, Deployment* first.
|
||||||
|
|
||||||
|
|
||||||
Next, you have to add new remote python interpreter, based on already tested deployment settings. Go to *Settings > Project > Project Interpreter*. Click on the cog icon, and click *Add Remote*.
|
Next, you have to add new remote python interpreter, based on already tested deployment settings. Go to *Settings > Project > Project Interpreter*. Click on the cog icon, and click *Add Remote*.
|
||||||
|
@ -48,7 +48,7 @@ After few seconds, all *Run/Debug Configurations* should be ready to use.
|
||||||
* run and debug tests
|
* run and debug tests
|
||||||
.. image:: images/f2.png
|
.. image:: images/f2.png
|
||||||
.. image:: images/f3.png
|
.. image:: images/f3.png
|
||||||
* run and debug migrations or different django managment commands
|
* run and debug migrations or different django management commands
|
||||||
.. image:: images/f4.png
|
.. image:: images/f4.png
|
||||||
* and many others..
|
* and many others..
|
||||||
|
|
||||||
|
|
37
{{cookiecutter.project_slug}}/ebsetenv.py
Normal file
37
{{cookiecutter.project_slug}}/ebsetenv.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
"""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()
|
|
@ -1,8 +1,10 @@
|
||||||
|
|
||||||
# PostgreSQL
|
# PostgreSQL
|
||||||
POSTGRES_PASSWORD=mysecretpass
|
POSTGRES_PASSWORD=mysecretpass
|
||||||
POSTGRES_USER=postgresuser
|
POSTGRES_USER=postgresuser
|
||||||
|
|
||||||
# General settings
|
# General settings
|
||||||
|
# DJANGO_READ_DOT_ENV_FILE=True
|
||||||
DJANGO_ADMIN_URL=
|
DJANGO_ADMIN_URL=
|
||||||
DJANGO_SETTINGS_MODULE=config.settings.production
|
DJANGO_SETTINGS_MODULE=config.settings.production
|
||||||
DJANGO_SECRET_KEY=CHANGEME!!!
|
DJANGO_SECRET_KEY=CHANGEME!!!
|
||||||
|
@ -16,6 +18,7 @@ DJANGO_AWS_STORAGE_BUCKET_NAME=
|
||||||
# Used with email
|
# Used with email
|
||||||
DJANGO_MAILGUN_API_KEY=
|
DJANGO_MAILGUN_API_KEY=
|
||||||
DJANGO_SERVER_EMAIL=
|
DJANGO_SERVER_EMAIL=
|
||||||
|
MAILGUN_SENDER_DOMAIN=
|
||||||
|
|
||||||
# Security! Better to use DNS for this task, but you can use redirect
|
# Security! Better to use DNS for this task, but you can use redirect
|
||||||
DJANGO_SECURE_SSL_REDIRECT=False
|
DJANGO_SECURE_SSL_REDIRECT=False
|
||||||
|
|
|
@ -48,7 +48,7 @@ gulp.task('styles', function() {
|
||||||
return gulp.src(paths.sass + '/project.scss')
|
return gulp.src(paths.sass + '/project.scss')
|
||||||
.pipe(sass().on('error', sass.logError))
|
.pipe(sass().on('error', sass.logError))
|
||||||
.pipe(plumber()) // Checks for errors
|
.pipe(plumber()) // Checks for errors
|
||||||
.pipe(autoprefixer({browsers: ['last 2 version']})) // Adds vendor prefixes
|
.pipe(autoprefixer({browsers: ['last 2 versions']})) // Adds vendor prefixes
|
||||||
.pipe(pixrem()) // add fallbacks for rem units
|
.pipe(pixrem()) // add fallbacks for rem units
|
||||||
.pipe(gulp.dest(paths.css))
|
.pipe(gulp.dest(paths.css))
|
||||||
.pipe(rename({ suffix: '.min' }))
|
.pipe(rename({ suffix: '.min' }))
|
||||||
|
@ -88,17 +88,8 @@ gulp.task('browserSync', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Default task
|
|
||||||
gulp.task('default', function() {
|
|
||||||
runSequence(['styles', 'scripts', 'imgCompression'], 'runServer', 'browserSync');
|
|
||||||
});
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//Watch//
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
// Watch
|
// Watch
|
||||||
gulp.task('watch', ['default'], function() {
|
gulp.task('watch', function() {
|
||||||
|
|
||||||
gulp.watch(paths.sass + '/*.scss', ['styles']);
|
gulp.watch(paths.sass + '/*.scss', ['styles']);
|
||||||
gulp.watch(paths.js + '/*.js', ['scripts']).on("change", reload);
|
gulp.watch(paths.js + '/*.js', ['scripts']).on("change", reload);
|
||||||
|
@ -106,3 +97,8 @@ gulp.task('watch', ['default'], function() {
|
||||||
gulp.watch(paths.templates + '/**/*.html').on("change", reload);
|
gulp.watch(paths.templates + '/**/*.html').on("change", reload);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Default task
|
||||||
|
gulp.task('default', function() {
|
||||||
|
runSequence(['styles', 'scripts', 'imgCompression'], 'runServer', 'browserSync', 'watch');
|
||||||
|
});
|
||||||
|
|
|
@ -5,6 +5,25 @@ import sys
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.local')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.local')
|
||||||
|
|
||||||
from django.core.management import execute_from_command_line
|
try:
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
except ImportError:
|
||||||
|
# The above import may fail for some other reason. Ensure that the
|
||||||
|
# issue is really that Django is missing to avoid masking other
|
||||||
|
# exceptions on Python 2.
|
||||||
|
try:
|
||||||
|
import django # noqa
|
||||||
|
except ImportError:
|
||||||
|
raise ImportError(
|
||||||
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
|
"available on your PYTHONPATH environment variable? Did you "
|
||||||
|
"forget to activate a virtual environment?"
|
||||||
|
)
|
||||||
|
raise
|
||||||
|
|
||||||
|
# This allows easy placement of apps within the interior
|
||||||
|
# {{ cookiecutter.project_slug }} directory.
|
||||||
|
current_path = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
sys.path.append(os.path.join(current_path, '{{ cookiecutter.project_slug }}'))
|
||||||
|
|
||||||
execute_from_command_line(sys.argv)
|
execute_from_command_line(sys.argv)
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
[pytest]
|
[pytest]
|
||||||
DJANGO_SETTINGS_MODULE=config.settings.local
|
DJANGO_SETTINGS_MODULE=config.settings.test
|
||||||
|
|
|
@ -1,61 +1,62 @@
|
||||||
{% if cookiecutter.use_python3 == 'y' -%}
|
|
||||||
# Wheel 0.25+ needed to install certain packages on CPython 3.5+
|
# Wheel 0.25+ needed to install certain packages on CPython 3.5+
|
||||||
# like Pillow and psycopg2
|
# like Pillow and psycopg2
|
||||||
# See http://bitly.com/wheel-building-fails-CPython-35
|
# See http://bitly.com/wheel-building-fails-CPython-35
|
||||||
# Verified bug on Python 3.5.1
|
# Verified bug on Python 3.5.1
|
||||||
wheel==0.29.0
|
wheel==0.29.0
|
||||||
{%- endif %}
|
|
||||||
|
|
||||||
# Bleeding edge Django
|
# Bleeding edge Django
|
||||||
django==1.9.9
|
django==1.10.7 # pyup: >=1.10,<1.11
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
django-environ==0.4.0
|
django-environ==0.4.3
|
||||||
{% if cookiecutter.use_whitenoise == 'y' -%}
|
{% if cookiecutter.use_whitenoise == 'y' -%}
|
||||||
whitenoise==3.2.1
|
whitenoise==3.3.0
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
|
|
||||||
# Forms
|
# Forms
|
||||||
django-braces==1.9.0
|
django-braces==1.11.0
|
||||||
django-crispy-forms==1.6.0
|
django-crispy-forms==1.6.1
|
||||||
|
|
||||||
# Models
|
# Models
|
||||||
django-model-utils==2.5.2
|
django-model-utils==3.0.0
|
||||||
|
|
||||||
# Images
|
# Images
|
||||||
Pillow==3.3.1
|
Pillow==4.1.1
|
||||||
|
|
||||||
|
# Password storage
|
||||||
|
argon2-cffi==16.3.0
|
||||||
|
|
||||||
# For user registration, either via email or social
|
# For user registration, either via email or social
|
||||||
# Well-built with regular release cycles!
|
# Well-built with regular release cycles!
|
||||||
django-allauth==0.27.0
|
django-allauth==0.32.0
|
||||||
|
|
||||||
{% if cookiecutter.windows == 'y' -%}
|
{% if cookiecutter.windows == 'y' -%}
|
||||||
# On Windows, you must download/install psycopg2 manually
|
# On Windows, you must download/install psycopg2 manually
|
||||||
# from http://www.lfd.uci.edu/~gohlke/pythonlibs/#psycopg
|
# from http://www.lfd.uci.edu/~gohlke/pythonlibs/#psycopg
|
||||||
{% else %}
|
{% else %}
|
||||||
# Python-PostgreSQL Database Adapter
|
# Python-PostgreSQL Database Adapter
|
||||||
psycopg2==2.6.2
|
psycopg2==2.7.1
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
# Unicode slugification
|
# Unicode slugification
|
||||||
awesome-slugify==1.6.5
|
awesome-slugify==1.6.5
|
||||||
django-autoslug==1.9.3
|
|
||||||
|
|
||||||
# Time zones support
|
# Time zones support
|
||||||
pytz==2016.6.1
|
pytz==2017.2
|
||||||
|
|
||||||
# Redis support
|
# Redis support
|
||||||
django-redis==4.4.4
|
django-redis==4.8.0
|
||||||
redis>=2.10.0
|
redis>=2.10.5
|
||||||
|
|
||||||
{% if cookiecutter.use_celery == "y" %}
|
{% if cookiecutter.use_celery == "y" %}
|
||||||
celery==3.1.23
|
celery==3.1.24
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if cookiecutter.use_compressor == "y" %}
|
{% if cookiecutter.use_compressor == "y" %}
|
||||||
rcssmin==1.0.6 {% if cookiecutter.windows == 'y' %}--install-option="--without-c-extensions"{% endif %}
|
rcssmin==1.0.6 {% if cookiecutter.windows == 'y' %}--install-option="--without-c-extensions"{% endif %}
|
||||||
django-compressor==2.1
|
django-compressor==2.1.1
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
# Your custom requirements go here
|
# Your custom requirements go here
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
# Local development dependencies go here
|
# Local development dependencies go here
|
||||||
-r base.txt
|
-r base.txt
|
||||||
coverage==4.2
|
|
||||||
django-coverage-plugin==1.3.1
|
coverage==4.3.4
|
||||||
Sphinx==1.4.5
|
django-coverage-plugin==1.5.0
|
||||||
django-extensions==1.7.4
|
|
||||||
Werkzeug==0.11.11
|
Sphinx==1.5.5
|
||||||
django-test-plus==1.0.15
|
django-extensions==1.7.8
|
||||||
factory_boy==2.7.0
|
Werkzeug==0.12.1
|
||||||
django-debug-toolbar==1.5
|
django-test-plus==1.0.17
|
||||||
|
factory-boy==2.8.1
|
||||||
|
|
||||||
|
django-debug-toolbar==1.7
|
||||||
|
|
||||||
# improved REPL
|
# improved REPL
|
||||||
ipdb==0.10.1
|
ipdb==0.10.3
|
||||||
|
|
||||||
pytest-django==2.9.1
|
pytest-django==3.1.2
|
||||||
pytest-sugar==0.7.1
|
pytest-sugar==0.8.0
|
||||||
|
|
|
@ -6,34 +6,34 @@
|
||||||
# Python-PostgreSQL Database Adapter
|
# Python-PostgreSQL Database Adapter
|
||||||
# If using Win for dev, this assumes Unix in prod
|
# If using Win for dev, this assumes Unix in prod
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
psycopg2==2.6.2
|
psycopg2==2.7.1
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
# WSGI Handler
|
# WSGI Handler
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
gevent==1.1.2
|
gevent==1.2.1
|
||||||
gunicorn==19.6.0
|
gunicorn==19.7.1
|
||||||
|
|
||||||
# Static and Media Storage
|
# Static and Media Storage
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
boto==2.42.0
|
boto==2.46.1
|
||||||
django-storages-redux==1.3.2
|
django-storages-redux==1.3.2
|
||||||
{% if cookiecutter.use_whitenoise != 'y' -%}
|
{% if cookiecutter.use_whitenoise != 'y' -%}
|
||||||
Collectfast==0.2.3
|
Collectfast==0.5.2
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
# Email backends for Mailgun, Postmark, SendGrid and more
|
# Email backends for Mailgun, Postmark, SendGrid and more
|
||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
django-anymail==0.4.2
|
django-anymail==0.9
|
||||||
|
|
||||||
{% if cookiecutter.use_sentry_for_error_reporting == "y" -%}
|
{% if cookiecutter.use_sentry_for_error_reporting == "y" -%}
|
||||||
# Raven is the Sentry client
|
# Raven is the Sentry client
|
||||||
# --------------------------
|
# --------------------------
|
||||||
raven==5.27.0
|
raven==6.0.0
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{% if cookiecutter.use_opbeat == "y" -%}
|
{% if cookiecutter.use_opbeat == "y" -%}
|
||||||
# Opbeat agent for performance monitoring
|
# Opbeat agent for performance monitoring
|
||||||
# -----------------------------------------
|
# -----------------------------------------
|
||||||
opbeat==3.4.0
|
opbeat==3.5.2
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
{% if cookiecutter.windows == 'y' -%}
|
{% if cookiecutter.windows == 'y' -%}
|
||||||
# Python-PostgreSQL Database Adapter
|
# Python-PostgreSQL Database Adapter
|
||||||
# If using Win for dev, this assumes Unix in test/prod
|
# If using Win for dev, this assumes Unix in test/prod
|
||||||
psycopg2==2.6.2
|
psycopg2==2.7.1
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
coverage==4.2
|
coverage==4.3.4
|
||||||
flake8==3.0.4 # pyup: != 2.6.0
|
flake8==3.3.0 # pyup: != 2.6.0
|
||||||
django-test-plus==1.0.15
|
django-test-plus==1.0.17
|
||||||
factory_boy==2.7.0
|
factory-boy==2.8.1
|
||||||
|
|
||||||
# pytest
|
# pytest
|
||||||
pytest-django==2.9.1
|
pytest-django==3.1.2
|
||||||
pytest-sugar==0.7.1
|
pytest-sugar==0.8.0
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{% if cookiecutter.use_python3 == 'y' -%}python-3.5.1{% else %}python-2.7.10{%- endif %}
|
python-3.5.3
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
max-line-length = 120
|
max-line-length = 120
|
||||||
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules
|
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules
|
||||||
|
|
||||||
[pep8]
|
[pycodestyle]
|
||||||
max-line-length = 120
|
max-line-length = 120
|
||||||
exclude=.tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules
|
exclude=.tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules
|
||||||
|
|
|
@ -6,11 +6,7 @@ PROJECT_DIR="$(dirname "$WORK_DIR")"
|
||||||
pip --version >/dev/null 2>&1 || {
|
pip --version >/dev/null 2>&1 || {
|
||||||
echo >&2 -e "\npip is required but it's not installed."
|
echo >&2 -e "\npip is required but it's not installed."
|
||||||
echo >&2 -e "You can install it by running the following command:\n"
|
echo >&2 -e "You can install it by running the following command:\n"
|
||||||
{% if cookiecutter.use_python3 == 'y' -%}
|
|
||||||
echo >&2 "wget https://bootstrap.pypa.io/get-pip.py --output-document=get-pip.py; chmod +x get-pip.py; sudo -H python3 get-pip.py"
|
echo >&2 "wget https://bootstrap.pypa.io/get-pip.py --output-document=get-pip.py; chmod +x get-pip.py; sudo -H python3 get-pip.py"
|
||||||
{% else %}
|
|
||||||
echo >&2 "wget https://bootstrap.pypa.io/get-pip.py --output-document=get-pip.py; chmod +x get-pip.py; sudo -H python2 get-pip.py"
|
|
||||||
{%- endif %}
|
|
||||||
echo >&2 -e "\n"
|
echo >&2 -e "\n"
|
||||||
echo >&2 -e "\nFor more information, see pip documentation: https://pip.pypa.io/en/latest/"
|
echo >&2 -e "\nFor more information, see pip documentation: https://pip.pypa.io/en/latest/"
|
||||||
exit 1;
|
exit 1;
|
||||||
|
@ -19,11 +15,7 @@ pip --version >/dev/null 2>&1 || {
|
||||||
virtualenv --version >/dev/null 2>&1 || {
|
virtualenv --version >/dev/null 2>&1 || {
|
||||||
echo >&2 -e "\nvirtualenv is required but it's not installed."
|
echo >&2 -e "\nvirtualenv is required but it's not installed."
|
||||||
echo >&2 -e "You can install it by running the following command:\n"
|
echo >&2 -e "You can install it by running the following command:\n"
|
||||||
{% if cookiecutter.use_python3 == 'y' -%}
|
|
||||||
echo >&2 "sudo -H pip3 install virtualenv"
|
echo >&2 "sudo -H pip3 install virtualenv"
|
||||||
{% else %}
|
|
||||||
echo >&2 "sudo -H pip2 install virtualenv"
|
|
||||||
{%- endif %}
|
|
||||||
echo >&2 -e "\n"
|
echo >&2 -e "\n"
|
||||||
echo >&2 -e "\nFor more information, see virtualenv documentation: https://virtualenv.pypa.io/en/latest/"
|
echo >&2 -e "\nFor more information, see virtualenv documentation: https://virtualenv.pypa.io/en/latest/"
|
||||||
exit 1;
|
exit 1;
|
||||||
|
@ -32,11 +24,7 @@ virtualenv --version >/dev/null 2>&1 || {
|
||||||
if [ -z "$VIRTUAL_ENV" ]; then
|
if [ -z "$VIRTUAL_ENV" ]; then
|
||||||
echo >&2 -e "\nYou need activate a virtualenv first"
|
echo >&2 -e "\nYou need activate a virtualenv first"
|
||||||
echo >&2 -e 'If you do not have a virtualenv created, run the following command to create and automatically activate a new virtualenv named "venv" on current folder:\n'
|
echo >&2 -e 'If you do not have a virtualenv created, run the following command to create and automatically activate a new virtualenv named "venv" on current folder:\n'
|
||||||
{% if cookiecutter.use_python3 == 'y' -%}
|
|
||||||
echo >&2 -e "virtualenv venv --python=\`which python3\`"
|
echo >&2 -e "virtualenv venv --python=\`which python3\`"
|
||||||
{% else %}
|
|
||||||
echo >&2 -e "virtualenv venv --python=\`which python2\`"
|
|
||||||
{%- endif %}
|
|
||||||
echo >&2 -e "\nTo leave/disable the currently active virtualenv, run the following command:\n"
|
echo >&2 -e "\nTo leave/disable the currently active virtualenv, run the following command:\n"
|
||||||
echo >&2 "deactivate"
|
echo >&2 "deactivate"
|
||||||
echo >&2 -e "\nTo activate the virtualenv again, run the following command:\n"
|
echo >&2 -e "\nTo activate the virtualenv again, run the following command:\n"
|
||||||
|
@ -52,4 +40,3 @@ else
|
||||||
pip install -r $PROJECT_DIR/requirements.txt
|
pip install -r $PROJECT_DIR/requirements.txt
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,7 @@
|
||||||
build-essential
|
build-essential
|
||||||
#required to translate
|
#required to translate
|
||||||
gettext
|
gettext
|
||||||
{% if cookiecutter.use_python3 == 'y' -%}
|
|
||||||
python3-dev
|
python3-dev
|
||||||
{% else %}
|
|
||||||
python-dev
|
|
||||||
{%- endif %}
|
|
||||||
|
|
||||||
##shared dependencies of:
|
##shared dependencies of:
|
||||||
##Pillow, pylibmc
|
##Pillow, pylibmc
|
||||||
|
|
|
@ -3,11 +3,7 @@
|
||||||
build-essential
|
build-essential
|
||||||
#required to translate
|
#required to translate
|
||||||
gettext
|
gettext
|
||||||
{% if cookiecutter.use_python3 == 'y' -%}
|
|
||||||
python3-dev
|
python3-dev
|
||||||
{% else %}
|
|
||||||
python-dev
|
|
||||||
{%- endif %}
|
|
||||||
|
|
||||||
##shared dependencies of:
|
##shared dependencies of:
|
||||||
##Pillow, pylibmc
|
##Pillow, pylibmc
|
||||||
|
@ -25,4 +21,3 @@ libwebp-dev
|
||||||
|
|
||||||
##django-extensions
|
##django-extensions
|
||||||
graphviz-dev
|
graphviz-dev
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,7 @@
|
||||||
build-essential
|
build-essential
|
||||||
#required to translate
|
#required to translate
|
||||||
gettext
|
gettext
|
||||||
{% if cookiecutter.use_python3 == 'y' -%}
|
|
||||||
python3-dev
|
python3-dev
|
||||||
{% else %}
|
|
||||||
python-dev
|
|
||||||
{%- endif %}
|
|
||||||
|
|
||||||
##shared dependencies of:
|
##shared dependencies of:
|
||||||
##Pillow, pylibmc
|
##Pillow, pylibmc
|
||||||
|
@ -25,4 +21,3 @@ libwebp-dev
|
||||||
|
|
||||||
##django-extensions
|
##django-extensions
|
||||||
graphviz-dev
|
graphviz-dev
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
__version__ = '{{ cookiecutter.version }}'
|
__version__ = '{{ cookiecutter.version }}'
|
||||||
__version_info__ = tuple([int(num) if num.isdigit() else num for num in __version__.replace('-', '.', 1).split('.')])
|
__version_info__ = tuple([int(num) if num.isdigit() else num for num in __version__.replace('-', '.', 1).split('.')])
|
||||||
|
|
|
@ -3,4 +3,3 @@ To understand why this file is here, please read:
|
||||||
|
|
||||||
http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
|
http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
|
||||||
"""
|
"""
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
|
@ -3,4 +3,3 @@ To understand why this file is here, please read:
|
||||||
|
|
||||||
http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
|
http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
|
||||||
"""
|
"""
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import models, migrations
|
|
||||||
import django.contrib.sites.models
|
import django.contrib.sites.models
|
||||||
|
from django.contrib.sites.models import _simple_domain_name_validator
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = []
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Site',
|
name='Site',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
('domain', models.CharField(verbose_name='domain name', max_length=100, validators=[django.contrib.sites.models._simple_domain_name_validator])),
|
('domain', models.CharField(
|
||||||
('name', models.CharField(verbose_name='display name', max_length=50)),
|
max_length=100, verbose_name='domain name', validators=[_simple_domain_name_validator]
|
||||||
|
)),
|
||||||
|
('name', models.CharField(max_length=50, verbose_name='display name')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name_plural': 'sites',
|
|
||||||
'verbose_name': 'site',
|
|
||||||
'db_table': 'django_site',
|
|
||||||
'ordering': ('domain',),
|
'ordering': ('domain',),
|
||||||
|
'db_table': 'django_site',
|
||||||
|
'verbose_name': 'site',
|
||||||
|
'verbose_name_plural': 'sites',
|
||||||
},
|
},
|
||||||
|
bases=(models.Model,),
|
||||||
managers=[
|
managers=[
|
||||||
(b'objects', django.contrib.sites.models.SiteManager()),
|
('objects', django.contrib.sites.models.SiteManager()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import django.contrib.sites.models
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('sites', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='site',
|
||||||
|
name='domain',
|
||||||
|
field=models.CharField(
|
||||||
|
max_length=100, unique=True, validators=[django.contrib.sites.models._simple_domain_name_validator],
|
||||||
|
verbose_name='domain name'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -3,10 +3,6 @@ To understand why this file is here, please read:
|
||||||
|
|
||||||
http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
|
http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
|
||||||
"""
|
"""
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations
|
from django.db import migrations
|
||||||
|
|
||||||
|
@ -38,7 +34,7 @@ def update_site_backward(apps, schema_editor):
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('sites', '0001_initial'),
|
('sites', '0002_alter_domain_unique'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
|
@ -3,4 +3,3 @@ To understand why this file is here, please read:
|
||||||
|
|
||||||
http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
|
http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
|
||||||
"""
|
"""
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{% if cookiecutter.use_celery == 'y' %}
|
{% if cookiecutter.use_celery == 'y' %}
|
||||||
from __future__ import absolute_import
|
|
||||||
import os
|
import os
|
||||||
from celery import Celery
|
from celery import Celery
|
||||||
from django.apps import apps, AppConfig
|
from django.apps import apps, AppConfig
|
||||||
|
@ -28,9 +27,19 @@ class CeleryConfig(AppConfig):
|
||||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
{% if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
||||||
if hasattr(settings, 'RAVEN_CONFIG'):
|
if hasattr(settings, 'RAVEN_CONFIG'):
|
||||||
# Celery signal registration
|
# Celery signal registration
|
||||||
|
{% if cookiecutter.use_pycharm == 'y' -%}
|
||||||
|
# Since raven is required in production only,
|
||||||
|
# imports might (most surely will) be wiped out
|
||||||
|
# during PyCharm code clean up started
|
||||||
|
# in other environments.
|
||||||
|
# @formatter:off
|
||||||
|
{%- endif %}
|
||||||
from raven import Client as RavenClient
|
from raven import Client as RavenClient
|
||||||
from raven.contrib.celery import register_signal as raven_register_signal
|
from raven.contrib.celery import register_signal as raven_register_signal
|
||||||
from raven.contrib.celery import register_logger_signal as raven_register_logger_signal
|
from raven.contrib.celery import register_logger_signal as raven_register_logger_signal
|
||||||
|
{% if cookiecutter.use_pycharm == 'y' -%}
|
||||||
|
# @formatter:on
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
raven_client = RavenClient(dsn=settings.RAVEN_CONFIG['DSN'])
|
raven_client = RavenClient(dsn=settings.RAVEN_CONFIG['DSN'])
|
||||||
raven_register_logger_signal(raven_client)
|
raven_register_logger_signal(raven_client)
|
||||||
|
@ -39,10 +48,20 @@ class CeleryConfig(AppConfig):
|
||||||
|
|
||||||
{% if cookiecutter.use_opbeat == 'y' -%}
|
{% if cookiecutter.use_opbeat == 'y' -%}
|
||||||
if hasattr(settings, 'OPBEAT'):
|
if hasattr(settings, 'OPBEAT'):
|
||||||
|
{% if cookiecutter.use_pycharm == 'y' -%}
|
||||||
|
# Since opbeat is required in production only,
|
||||||
|
# imports might (most surely will) be wiped out
|
||||||
|
# during PyCharm code clean up started
|
||||||
|
# in other environments.
|
||||||
|
# @formatter:off
|
||||||
|
{%- endif %}
|
||||||
from opbeat.contrib.django.models import client as opbeat_client
|
from opbeat.contrib.django.models import client as opbeat_client
|
||||||
from opbeat.contrib.django.models import logger as opbeat_logger
|
from opbeat.contrib.django.models import logger as opbeat_logger
|
||||||
from opbeat.contrib.django.models import register_handlers as opbeat_register_handlers
|
from opbeat.contrib.django.models import register_handlers as opbeat_register_handlers
|
||||||
from opbeat.contrib.celery import register_signal as opbeat_register_signal
|
from opbeat.contrib.celery import register_signal as opbeat_register_signal
|
||||||
|
{% if cookiecutter.use_pycharm == 'y' -%}
|
||||||
|
# @formatter:on
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opbeat_register_signal(opbeat_client)
|
opbeat_register_signal(opbeat_client)
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
{% raw %}{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Forbidden (403){% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>Forbidden (403)</h1>
|
||||||
|
|
||||||
|
<p>CSRF verification failed. Request aborted.</p>
|
||||||
|
{% endblock content %}{% endraw %}
|
|
@ -1,9 +1,9 @@
|
||||||
{% raw %}{% extends "base.html" %}
|
{% raw %}{% extends "base.html" %}
|
||||||
|
|
||||||
{% block title %}Page Not found{% endblock %}
|
{% block title %}Page not found{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Page Not found</h1>
|
<h1>Page not found</h1>
|
||||||
|
|
||||||
<p>This is not the page you were looking for.</p>
|
<p>This is not the page you were looking for.</p>
|
||||||
{% endblock content %}{% endraw %}
|
{% endblock content %}{% endraw %}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<form method="POST" action="{% url 'account_reset_password' %}" class="password_reset">
|
<form method="POST" action="{% url 'account_reset_password' %}" class="password_reset">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
<input type="submit" value="{% trans 'Reset My Password' %}" />
|
<input class="btn btn-primary" type="submit" value="{% trans 'Reset My Password' %}" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<p>{% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}</p>
|
<p>{% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}</p>
|
||||||
|
|
|
@ -10,12 +10,12 @@
|
||||||
|
|
||||||
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
|
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||||
<!--[if lt IE 9]>
|
<!--[if lt IE 9]>
|
||||||
<script src="https://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
<!-- Latest compiled and minified Bootstrap 4 Alpha 3 CSS -->
|
<!-- Latest compiled and minified Bootstrap 4 Alpha 4 CSS -->
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.3/css/bootstrap.min.css" integrity="sha384-MIwDKRSSImVFAZCVLtU0LMDdON6KVCrZHyVQQj6e8wIEJkW4tvwqXrbMIya1vriY" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
|
||||||
|
|
||||||
<!-- Your stuff: Third-party CSS libraries go here -->
|
<!-- Your stuff: Third-party CSS libraries go here -->
|
||||||
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress css %}{% endraw %}{% endif %}{% raw %}
|
{% endraw %}{% if cookiecutter.use_compressor == "y" %}{% raw %}{% compress css %}{% endraw %}{% endif %}{% raw %}
|
||||||
|
@ -29,44 +29,43 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="m-b-1">
|
<div class="m-b-1">
|
||||||
<nav class="navbar navbar-dark navbar-static-top bg-inverse">
|
<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
|
||||||
<div class="container">
|
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<a class="navbar-brand" href="/">{% endraw %}{{ cookiecutter.project_name }}{% raw %}</a>
|
<span class="navbar-toggler-icon"></span>
|
||||||
<button type="button" class="navbar-toggler hidden-sm-up pull-xs-right" data-toggle="collapse" data-target="#bs-navbar-collapse-1">
|
</button>
|
||||||
☰
|
<a class="navbar-brand" href="{% url 'home' %}">{% endraw %}{{ cookiecutter.project_name }}{% raw %}</a>
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
<div class="collapse navbar-toggleable-xs" id="bs-navbar-collapse-1">
|
<ul class="navbar-nav mr-auto">
|
||||||
<ul class="nav navbar-nav">
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="{% url 'home' %}">Home <span class="sr-only">(current)</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'about' %}">About</a>
|
||||||
|
</li>
|
||||||
|
{% if request.user.is_authenticated %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{% url 'home' %}">Home</a>
|
{# URL provided by django-allauth/account/urls.py #}
|
||||||
|
<a class="nav-link" href="{% url 'users:detail' request.user.username %}">{% trans "My Profile" %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{% url 'about' %}">About</a>
|
{# URL provided by django-allauth/account/urls.py #}
|
||||||
|
<a class="nav-link" href="{% url 'account_logout' %}">{% trans "Sign Out" %}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
{% else %}
|
||||||
|
<li class="nav-item">
|
||||||
<ul class="nav navbar-nav pull-xs-right">
|
{# URL provided by django-allauth/account/urls.py #}
|
||||||
{% if request.user.is_authenticated %}
|
<a id="sign-up-link" class="nav-link" href="{% url 'account_signup' %}">{% trans "Sign Up" %}</a>
|
||||||
<li class="nav-item">
|
</li>
|
||||||
<a class="nav-link" href="{% url 'users:detail' request.user.username %}">{% trans "My Profile" %}</a>
|
<li class="nav-item">
|
||||||
</li>
|
{# URL provided by django-allauth/account/urls.py #}
|
||||||
<li class="nav-item">
|
<a id="log-in-link" class="nav-link" href="{% url 'account_login' %}">{% trans "Sign In" %}</a>
|
||||||
<a class="nav-link" href="{% url 'account_logout' %}">{% trans "Sign Out" %}</a>
|
</li>
|
||||||
</li>
|
{% endif %}
|
||||||
{% else %}
|
</ul>
|
||||||
<li class="nav-item">
|
|
||||||
<a id="sign-up-link" class="nav-link" href="{% url 'account_signup' %}">{% trans "Sign Up" %}</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a id="log-in-link" class="nav-link" href="{% url 'account_login' %}">{% trans "Sign In" %}</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
@ -89,10 +88,10 @@
|
||||||
================================================== -->
|
================================================== -->
|
||||||
<!-- Placed at the end of the document so the pages load faster -->
|
<!-- Placed at the end of the document so the pages load faster -->
|
||||||
{% block javascript %}
|
{% block javascript %}
|
||||||
<!-- Required by Bootstrap v4 Alpha 3 -->
|
<!-- Required by Bootstrap v4 Alpha 4 -->
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js" integrity="sha384-THPy051/pYDQGanwU6poAc/hOdQxjnOEXzbT+OuUAFqNqFjL+4IGLBgCJC3ZOShY" crossorigin="anonymous"></script>
|
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.2.0/js/tether.min.js" integrity="sha384-Plbmg8JY28KFelvJVai01l8WyZzrYWG825m+cZ0eDDS1f7d/js6ikvy1+X+guPIB" crossorigin="anonymous"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
|
||||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.3/js/bootstrap.min.js" integrity="sha384-ux8v3A6CPtOTqOzMKiuo3d/DomGaaClxFYdCu2HPMBEkf6x2xiDyJ7gkXU0MWwaD" crossorigin="anonymous"></script>
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
<!-- Your stuff: Third-party javascript libraries go here -->
|
<!-- Your stuff: Third-party javascript libraries go here -->
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
|
@ -1,4 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from allauth.account.adapter import DefaultAccountAdapter
|
from allauth.account.adapter import DefaultAccountAdapter
|
||||||
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
|
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
|
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
|
||||||
|
|
|
@ -1,44 +1,43 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import models, migrations
|
|
||||||
import django.utils.timezone
|
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
import django.core.validators
|
import django.contrib.auth.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('auth', '0006_require_contenttypes_0002'),
|
('auth', '0008_alter_user_username_max_length'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='User',
|
name='User',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||||
('last_login', models.DateTimeField(null=True, verbose_name='last login', blank=True)),
|
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
||||||
('is_superuser', models.BooleanField(help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status', default=False)),
|
('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(max_length=30, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.', 'invalid')], verbose_name='username', error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True)),
|
('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(max_length=30, verbose_name='first name', blank=True)),
|
('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
|
||||||
('last_name', models.CharField(max_length=30, verbose_name='last name', blank=True)),
|
('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')),
|
||||||
('email', models.EmailField(max_length=254, verbose_name='email address', blank=True)),
|
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
|
||||||
('is_staff', models.BooleanField(help_text='Designates whether the user can log into this admin site.', verbose_name='staff status', default=False)),
|
('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(help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active', default=True)),
|
('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')),
|
||||||
('date_joined', models.DateTimeField(verbose_name='date joined', default=django.utils.timezone.now)),
|
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||||
('groups', models.ManyToManyField(related_name='user_set', blank=True, verbose_name='groups', to='auth.Group', help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_query_name='user')),
|
('name', models.CharField(blank=True, max_length=255, verbose_name='Name of User')),
|
||||||
('user_permissions', models.ManyToManyField(related_name='user_set', blank=True, verbose_name='user permissions', to='auth.Permission', help_text='Specific permissions for this user.', related_query_name='user')),
|
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
|
||||||
('name', models.CharField(max_length=255, verbose_name='Name of User', blank=True)),
|
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
|
'verbose_name_plural': 'users',
|
||||||
'verbose_name': 'user',
|
'verbose_name': 'user',
|
||||||
'abstract': False,
|
'abstract': False,
|
||||||
'verbose_name_plural': 'users',
|
|
||||||
},
|
},
|
||||||
managers=[
|
managers=[
|
||||||
(b'objects', django.contrib.auth.models.UserManager()),
|
('objects', django.contrib.auth.models.UserManager()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
|
@ -6,14 +6,14 @@ from ..admin import MyUserCreationForm
|
||||||
class TestMyUserCreationForm(TestCase):
|
class TestMyUserCreationForm(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user = self.make_user()
|
self.user = self.make_user('notalamode', 'notalamodespassword')
|
||||||
|
|
||||||
def test_clean_username_success(self):
|
def test_clean_username_success(self):
|
||||||
# Instantiate the form with a new username
|
# Instantiate the form with a new username
|
||||||
form = MyUserCreationForm({
|
form = MyUserCreationForm({
|
||||||
'username': 'alamode',
|
'username': 'alamode',
|
||||||
'password1': '123456',
|
'password1': '7jefB#f@Cc7YJB]2v',
|
||||||
'password2': '123456',
|
'password2': '7jefB#f@Cc7YJB]2v',
|
||||||
})
|
})
|
||||||
# Run is_valid() to trigger the validation
|
# Run is_valid() to trigger the validation
|
||||||
valid = form.is_valid()
|
valid = form.is_valid()
|
||||||
|
@ -27,8 +27,8 @@ class TestMyUserCreationForm(TestCase):
|
||||||
# Instantiate the form with the same username as self.user
|
# Instantiate the form with the same username as self.user
|
||||||
form = MyUserCreationForm({
|
form = MyUserCreationForm({
|
||||||
'username': self.user.username,
|
'username': self.user.username,
|
||||||
'password1': '123456',
|
'password1': 'notalamodespassword',
|
||||||
'password2': '123456',
|
'password2': 'notalamodespassword',
|
||||||
})
|
})
|
||||||
# Run is_valid() to trigger the validation, which is going to fail
|
# Run is_valid() to trigger the validation, which is going to fail
|
||||||
# because the username is already taken
|
# because the username is already taken
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import absolute_import, unicode_literals
|
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.views.generic import DetailView, ListView, RedirectView, UpdateView
|
from django.views.generic import DetailView, ListView, RedirectView, UpdateView
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user