merge master to pycharm_support branch

This commit is contained in:
Krzysztof Szumny 2016-03-23 11:35:39 +01:00
commit d319610b3a
99 changed files with 3252 additions and 1012 deletions

View File

@ -12,7 +12,7 @@ trim_trailing_whitespace = true
indent_style = space
indent_size = 4
[*.yml]
[*.{html,css,scss,json,yml}]
indent_style = space
indent_size = 2

12
.gitignore vendored
View File

@ -24,8 +24,20 @@ sftp-config.json
*.pot
*.pyc
.idea
_build
# Project Specific Stuff
local_settings.py
repo_name
my_test_project/*
# Generated when running py.test for the cookiecutter-django generation tests
.cache/
# Generated when running celery beat
celerybeat-schedule.db
# Unit test / coverage reports
.coverage
.tox
.cache

View File

@ -1,11 +1,33 @@
language: python
sudo: false
# Config file for automatic testing at travis-ci.org
install:
- pip install -r requirements.txt
sudo: required
services:
- docker
language: python
python: 3.5
env:
- TOX_ENV=py27
- TOX_ENV=py34
- TOX_ENV=py35
before_install:
- sudo apt-get update
- sudo apt-get install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" docker-engine=1.10.1-0~trusty
- sudo rm /usr/local/bin/docker-compose
- curl -L https://github.com/docker/compose/releases/download/1.6.0/docker-compose-`uname -s`-`uname -m` > docker-compose
- chmod +x docker-compose
- sudo mv docker-compose /usr/local/bin
script:
- py.test
- tox -e $TOX_ENV
- sh tests/test_docker.sh
install:
- pip install tox
notifications:
email:

View File

@ -2,6 +2,482 @@
All enhancements and patches to cookiecutter-django will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
### [2016-03-16]
### Changed
- Set the correct postgres username in dev.yml (@calculuscowboy)
## [2016-03-14]
### Changed
- Enforce `repo_name` as proper python module (@catherinedevlin)
## [2016-03-08]
### Changed
- Docker configuration now uses docker-compose format v2 (@aeikenberry)
- Make sure that STATIC_URL != MEDIA_URL (@cdvv7788)
- fix minor typos in project README (@menzenski)
- Updated docker docs (@jayfk)
### Added
- Added database controls for docker (@jayfk)
## [2016-03-05]
### Changed
- Update version of Django, celery, django-test-plus (@luzfcb)
- Update version of Hitch tests dependencies: jupyter_client (@luzfcb)
- Update 'now' date in cookiecutter.json (@luzfcb)
- Update the usage example in README (@luzfcb)
## [2016-03-01]
### Changed
- Update version of Django, flake8, pyflakes, pytest, factory_boy, ipdb, Werkzeug, gevent (@luzfcb)
- Update version of Hitch tests dependencies: click, hitchserve, hitchsystem, hitchtest, ipython, psutil, python-dateutil(@luzfcb)
- Update Tether (JS) version to 1.2.0 (@luzfcb)
## [2016-02-24]
### Added
- Beginning support for `py.test` (@pydanny)
### Changed
- Fixed missing div closing tag for "container" on user_list.html (@Eraldo)
## [2016-02-18]
### Changed
- The status of the registration (open or closed) is now read from the project environment instead of hardcoded in the common settings file. (@Eraldo)
- Renamed the adapter.py file to adapters.py to match the django naming convention. (@Eraldo)
## [2016-02-15]
### Changed
- In `users` app adapter, fix `is_open_for_signup` missing parameter (@oryx2)
- Fixes and improvements in Hitch tests , see [#485](https://github.com/pydanny/cookiecutter-django/pull/485) (@crdoconnor)
## [2016-02-12]
### Changed
- Fixed typo (@yunti)
## [2016-02-07]
### Changed
- In `users` app, use Django 1.9 `LoginRequiredMixin` instead of django-braces implementation (@yunti)
- Update native OS libraries of Hitch Test, because [unixpackage](https://github.com/unixpackage/unixpackage) now supports multiple versions of same Linux distribution (@crdoconnor)
- Update AngularJS version to 1.5.0 (@luzfcb)
- Update version of wheel, Pillow, django_coverage_plugin (@luzfcb)
- Update version of Hitch tests dependencies: decorator, hitchselenium, ipython, ptyprocess, selenium (@luzfcb)
- Provided options for FOSS license choices, or for private efforts, no written license (@pydanny)
## [2016-02-01]
### Changed
- Update version of Django and django-floppyforms (@luzfcb)
- Update version of Hitch tests dependencies: hitchpython and selenium (@luzfcb)
## [2016-01-30]
### Changed
- Update flake8 to 2.5.2 (@luzfcb)
## [2016-01-29]
### Changed
- Update AngularJS version to 1.4.9 (@luzfcb)
- Update jQuery version to 2.2.0 (@luzfcb)
- Update 'now' date in cookiecutter.json (@luzfcb)
- Update version of boto, celery, django_coverage_plugin, django-storages-redux, flake8, gevent, gunicorn, pep8, pytest, tox, Werkzeug (@luzfcb)
- Update version of Hitch tests dependencies: colorama, decorator, hitchpostgres, hitchpython, hitchredis, hitchselenium, hitchserve, hitchsystem, hitchtest, ipython, patool, pickleshare, psutil, python-build, requests, selenium, tblib, traitlets (@luzfcb)
## [2016-01-26]
### Changed
- Fixed NEW_RELIC_APP_NAME environment variable (@jayfk)
## [2016-1-18]
### Added
- Added .dockerignore file (@bogdal)
- Docker tests for travis (@jayfk)
### Changed
- Removed the $-sign from allowed chars to generate the secret key (@jayfk)
## [2016-01-17]
### Added
- Adding a section on third party articles referencing `cookiecutter-django` (@mjheo)
### Changed
- Add celerybeat db to gitignore (@originell)
## [2016-01-16]
### Added
- Adding an explanation for having `django.contrib.sites`. (@pydanny)
## [2016-01-13]
### Changed
- Update setup.py version to 1.9.1 to match Django version. (@Collederas)
- Require Wheel 0.26.0. Needed to install certain packages on CPython 3.5+ like Pillow and psycopg2 (@audreyr)
## [2016-01-09]
### Changed
- Upgraded django-extensions to 1.6.1 as it fixes a [JSONField bug](https://github.com/django-extensions/django-extensions/blob/master/CHANGELOG.md#161) (@burhan)
- Upgraded Pillow to version 3.1.0 ([upstream changelog](https://github.com/python-pillow/Pillow/blob/master/CHANGES.rst#310-2016-01-04)) (@burhan)
- Upgraded django to 1.9.1 to integrate various [bugfixes](https://docs.djangoproject.com/en/1.9/releases/1.9.1/) (@burhan)
- Upgraded django-crispy-forms to 1.6 for [BS4 and django 1.9 compatibility fixes](https://github.com/maraujop/django-crispy-forms/blob/dev/CHANGELOG.md#160-201617) (@burhan)
- Upgraded django-model-utils to 2.4, to enable [support for django 1.9](https://github.com/carljm/django-model-utils/blob/master/CHANGES.rst#24-2015-12-03) (@burhan)
## [2016-01-08]
### Changed
- Fixed redis url on docker (@jayfk)
- Fixed docker on windows (@burhan)
## [2016-01-06]
### Added
- You can now enable or disable user registration using the ACCOUNT_ALLOW_REGISTRATION setting. (@ddiazpinto)
### Changed
- Use Postgres 9.5 on docker (@jayfk)
## [2016-01-04]
### Added
- Add Tether.js because [is needed](http://v4-alpha.getbootstrap.com/components/tooltips/#overview) for proper positioning of Bootstrap tooltips (@EricZaporzan)
### Changed
- Minor fixes in the docker documentation (@jayfk)
- Made @burhan a core committer (@pydanny)
## [2015-12-30]
### Changed
- Fixed a bug where the navbar was not displayed correctly (@jvanbrug)
## [2015-12-21]
### Changed
- Added sentry logger to celery config (@jayfk)
## [2015-12-16]
- Update preview 4xx error pages to accept `exception` argument (@theskumar)
## [2015-12-15]
### Changed
- Fix celery worker app name in Procfile (@stepmr)
## [2015-12-13]
### Changed
- Bumped Django to 1.9 (@areski)
- Support opbeat logging with celery (@stepmr)
- Update runtime.txt with PY2 support (@stepmr)
## [2015-12-12]
### Added
- Celery worker to Heroku procfile (@stepmr)
## [2015-12-11]
### Changed
- Fixed issue #436 - cookiecutter variable name was renamed from `celery_support` to `use_celery` in `tests/engine.py` (@luzfcb @otakucode)
- Updated Heroku runtime.txt for python 3.5.1 (@yunti)
## [2015-12-06]
### Changed
- Reorganization of contributors (@burhan)
## [2015-12-01]
### Changed
- Update documentation to include the installation os dependencies before development requirements (@failsafe86)
## [2015-11-29]
### Changed
- Update version of click and python-build (@luzfcb)
## [2015-11-25]
### Changed
- Update version of psutil, ipython (@luzfcb)
- Update version of gunicorn (@audreyr)
- Remove debugging tools from non-generated part of cookiecutter-django, since those are personal prefs (@audreyr)
- Update version of Django in setup.py (@luzfcb)
## [2015-11-24]
### Changed
- Update version of Django, coverage and click (@luzfcb)
- Fixed configuration for Celery in local.py. (@luzfcb @hackebrot)
## [2015-11-23]
### Changed
- Update AngularJS version to 1.4.8 (@luzfcb)
- Update version of cookiecutter, pytest, tox, whitenoise, django-test-plus, django_coverage_plugin, Werkzeug, hitchserve, tornado, unixpackage (@luzfcb)
- Update 'now' date in cookiecutter.json (@luzfcb)
- `sh` package version pinned to `1.11` (@luzfcb)
## [2015-11-22]
### Changed
- Move div class unquote outside the django if tag (@jvanbrug)
- Changed gevent to `1.1rc1` for python 3 users (@jondelmil / @jayfk)
## [2015-11-20]
### Changed
- Using python 3.5 on Heroku/Travis (@bogdal)
- Fixed typo in README (@tedmiston)
## [2015-11-18]
### Added
- Mailhog as a replacement for Maildump (@keybits)
### Removed
- Maildump because it didn't support Python 3 (@keybits)
## [2015-11-17]
### Added
- initial configuration to support opbeat (@burhan)
### Removed
- Took `*.pyc` out of .gitignore, because it's already covered by `*.py[cod]` (@audreyr)
## [2015-11-16]
### Changed
- Cleanup of main README (@burhan)
## [2015-11-15]
### Added
- Added `UserFactory` for users.User tests (@ad-m)
## [2015-11-12]
### Changed
- Update version of django-allauth (@yunti)
- Added a warning in README.rst: ```repo_name must be a valid Python module``` @cdvv7788
### Removed
- remove ```{% load url from future %}``` in templates - deprecated in django 1.9 (@yunti)
## [2015-11-11]
### Added
- Added django_coverage_plugin to measure Django template coverage (@audreyr)
## [2015-11-09]
### Changed
- Now using py.test for our test suite!! (@hackebrot)
- Python version in travis.yml is now correct for the selected version of Django (@show0k)
## [2015-11-08]
### Changed
- bump django-extensions version (@garrypolley)
## [2015-11-07]
### Added
- newrelic support (@amjith)
- DJANGO_SENTRY_DSN to env.example (@jayfk)
### Changed
- Made `post_gen_hook.set_secret_key()` only changes one CHANGEME!!! at a time. (@pydanny)
- Fixed an error where celery couldn't load the sentry DSN from settings (@jayfk)
- Renamed ADMIN_URL to DJANGO_ADMIN_URL in env.example (@ChrisPappalardo)
## [2015-11-06]
### Added
- \*tests\* to `.coveragerc`, because including it is cheating! (@pydanny)
- Binaryornot to cookiecutter-django's own tests because otherwise Python 3 blows up (@audreyr)
### Changed
- `.travis.yml` configuration to support Python 3.4 and 3.5 (@pydanny)
- `.gitignore` configuration so py.test cache files don't show up in git status.
## [2015-11-05]
### Changed
- Update version of django-extensions (@luzfcb)
- Fix gevent requirement for Python 3 (@mcho421)
## [2015-11-04]
### Changed
- Update version of Django, cookiecutter, celery, coverage, django-mailgun, django-redis, factory_boy, flake8, pytest and pytz (@luzfcb)
- Update AngularJS version to 1.4.7 (@luzfcb)
- Update 'now' date in cookiecutter.json (@luzfcb)
## [2015-10-28]
### Changed
- Update deployment-on-heroku.rst for ADMIN_URL (@yunti)
## [2015-10-27]
### Added
- Added sudo: true to the travis file (@MathijsHoogland)
## [2015-10-25]
### Added
- Move current logging config into production.py since it's not useful locally anyway. Used only if not using Sentry. (@audreyr)
- `setup.py` so we can list it on PyPI and therefore displayed on djangopackages.com as compatible with Python 3. (@pydanny)
- Versioning and tagging policy (@pydanny)
- Fixed flake8 issue (@pydanny)
## [2015-10-24]
### Changed
- Update nav in base template to latest Bootstrap 4 version (@audreyr)
- Replaced ADD with COPY in dockerfiles (@audreyr)
- Simplified development dockerfile (@jayfk)
- Moved the docker postgres volume on the development environment to it's own subfolder (@jayfk)
- Renamed DJANGO_CACHE_URL to REDIS_URL (@jayfk / proposed by @pydanny)
## [2015-10-22]
### Removed
- Remove unnecessary .gitkeep in static/images/ (@audreyr)
## [2015-10-21]
### Changed
- Updated requirements (@theskumar)
### Removed
- editorconfig comment that was just a isort settings link (@pydanny)
## [2015-10-19]
### Changed
- On Windows, don't install psycopg2 locally. Still install it in test/prod which are assumed to be Unix. (@audreyr)
## [2015-10-15]
### Changed
- Made `post_gen_hook` function to change secret keys in files more generic (@pydanny)
- Set cryptographically randomized value to `DJANGO_SECRET_KEY` in `env.example` (@pydanny)
## [2015-10-14]
### Added
- Documention of project options (@audreyr)
### Changed
- Added clarification on building for local or production (@MathijsHoogland)
- Whitespace correction in dev.yml (@MathijsHoogland)
## [2015-10-13]
### Changed
- Requirements update (@theskumar)
## [2015-10-11]
### Changed
- Fixed raven issue on development (#302) (@jazztpt)
## [2015-10-05]
### Changed
- Update version of Django, Pillow, hitchselenium, psutil (@luzfcb)
## [2015-10-04]
### Changed
- Remove stray closing tags and fix navbar margin in in base.html (@hairychris)
- Docker docs to be functional and more understandable (@audreyr)
## [2015-09-30]
### Changed
- Fixed Sentry logging with celery (@jayfk)
- Added pep8 and pyflakes to requirements (@jayfk)
- Fixed url() arguments in urls.py because String view arguments to url() is deprecated in django 1.9 (@siauPatrick)
- Update version of cookiecutter, coverage, django-environ, django-extensions, hitchpython, hitchselenium, hitchserve, pytest, pytz, whitenoise (@luzfcb)
- Update the usage example in README (@luzfcb)
- Update 'now' date in cookiecutter.json (@luzfcb)
## [2015-09-29]
### Changed
- Fix RST in Docker docs (@andor-pierdelacabeza)
## [2015-09-27]
### Added
- Added advice on how to persist changes with boot2docker (@jayfk)
###Changed
- Removed duplicate from `CONTRIBUTORS.rst` (@jayfk)
## [2015-09-26]
### Added
- Add .pylintrc and .pep8 (@kaidokert)
### Changed
- Move pep8 rules to setup.cfg (@audreyr)
- Better pep8 rules for exclusion (@audreyr)
- Document all linters (@audreyr)
- Sass linting and improvements to alerts (@audreyr)
## [2015-09-25]
### Changed
- django-mailgun requirement to 0.7.2 (@pydanny)
- Remove commented-out flake8 ignore rule. (@audreyr)
## [2015-09-24]
### Changed
- Add user-uploaded media dir to .gitignore (@audreyr)
- Update .editorconfig to use 2 spaces for html, css, scss, json (@audreyr)
- Have flake8 ignore node_modules dir (@audreyr)
## [2015-09-23]
### Changed
- Add workaround for django-debug-toolbar conflict with Bootstrap 4 (@audreyr)
## [2015-09-22]
### Added
- Add Python version option for deployment (@yunti)
## [2015-09-21]
### Changed
- django-mailgun-redux to django-mailgun, because @pydanny now has commit rights
### Removed
- Excess "loggers" from LOGGING setting (@siauPatrick)
## [2015-09-18]
### Changed
- Major reorganization of docs (@pydanny)
- Fix expanded navbar on mobile (@jayfk)
- Update various requirements (@audreyr)
## [2015-09-17]
### Added
- Fix for wsgi.py for Raven in dev (@yunti)
## [2015-09-15]
### Added
- whitespace to allow proper rendering of RST (@IanLee1521 )
## [2015-09-14]
### Added
- Functionality to delete taskapp if celery isn't going to be used (@pydanny)
### Removed
- Remove unused generated CSS styles (@audreyr)
### Changed
- Use Bootstrap margin utility class `m-b-lg` and remove our custom `navbar-header` class (@audreyr)
- Update Hitch requirements (@audreyr)
## [2015-09-13]
### Removed
- Styles that already exist in Bootstrap 4 (or 3) (@audreyr)
### Changed
- Fix issue #296 - change login.html to use [get_providers](https://github.com/pennersr/django-allauth/blob/master/allauth/socialaccount/templatetags/socialaccount.py#L84-L93) templatetag because ``allauth.socialaccount`` context processor now is [deprecated](http://django-allauth.readthedocs.org/en/latest/changelog.html#from-0-21-0) (@luzfcb)
## [2015-09-09]
### Added
- post_gen_hook to generate a secret key for use in locals.py. You should define your own for production (@pydanny)
## [2015-09-09]
### Added
- htmlcov to gitignore (@pydanny)
## [2015-09-04]
### Added
- Easy deploy Heroku button and app.json file (@bogdal)
## [2015-09-03]
### Added
- For security reasons, we set explicitly the list of allowed hosts (@bogdal)
## [2015-08-31]
### Removed
- Dokku in favor of docker-compose and other modern Django tools (@pydanny)
## [2015-08-30]
### Changed
- Moved from Bootstrap 3 to Bootstrap 4 (@audreyr)
- Slight Reorganization of the README docs (@pydanny)
- Dokku docs are out of the README and in the docs folder (@pydanny)
- Small improvements in ``install_python_dependencies.sh`` and ``install_os_dependencies.sh`` scripts (@luzfcb)
- Update version of django-crispy-forms, django-extensions, django-test-plus, gevent, coverage, hitchpython and hitchtest (@luzfcb)
- Update AngularJS version to 1.4.4 (@luzfcb)
- Update the usage example on README (@luzfcb)
## [2015-08-28]
### Changed
- Switched to django-mailgun-redux so mail doesn't blow up on Python 3 (@pydanny)
## [2015-08-27]
### Changed
- Grunt Updates: use libsass, add postcss (@288)
## [2015-08-20]
### Changed
- requirements files to match current dependency versions (@pydanny)

View File

@ -9,3 +9,48 @@ Getting your pull request merged in
#. Keep it small. The smaller the pull request the more likely I'll pull it in.
#. Pull requests that fix a current issue get priority for review.
#. If you're not already in the `CONTRIBUTORS.rst` file, add yourself!
Testing
-------
Installation
~~~~~~~~~~~~
Please install `tox`_, which is a generic virtualenv management and test command line tool.
`tox`_ is available for download from `PyPI`_ via `pip`_::
$ pip install tox
It will automatically create a fresh virtual environment and install our test dependencies,
such as `pytest-cookies`_ and `flake8`_.
Run the Tests
~~~~~~~~~~~~~
Tox uses py.test under the hood, hence it supports the same syntax for selecting tests.
For further information please consult the `pytest usage docs`_.
To run all tests using various versions of python in virtualenvs defined in tox.ini, just run tox.::
$ tox
It is possible to tests with some versions of python, to do this the command
is::
$ tox -e py27,py34
Will run py.test with the python2.7, and python3.4 interpreters, for
example.
To run a particular test with tox for against your current Python version::
$ tox -e py -- -k test_default_configuration
.. _`pytest usage docs`: https://pytest.org/latest/usage.html#specifying-tests-selecting-tests
.. _`tox`: https://tox.readthedocs.org/en/latest/
.. _`pip`: https://pypi.python.org/pypi/pip/
.. _`pytest-cookies`: https://pypi.python.org/pypi/pytest-cookies/
.. _`flake8`: https://pypi.python.org/pypi/flake8/
.. _`PyPI`: https://pypi.python.org/pypi

164
CONTRIBUTORS.rst Normal file
View File

@ -0,0 +1,164 @@
Contributors
============
Core Developers
----------------
These contributors have commit flags for the repository,
and are able to accept and merge pull requests.
=========================== ============= ===========
Name Github Twitter
=========================== ============= ===========
Daniel Roy Greenfeld `@pydanny`_ @pydanny
Audrey Roy Greenfeld* `@audreyr`_ @audreyr
Fábio C. Barrionuevo da Luz `@luzfcb`_ @luzfcb
Saurabh Kumar `@theskumar`_ @_theskumar
Jannis Gebauer `@jayfk`_
Burhan Khalid `@burhan`_ @burhan
=========================== ============= ===========
*Audrey is also the creator of Cookiecutter. Audrey and
Daniel are on the Cookiecutter core team.*
.. _@pydanny: https://github.com/pydanny
.. _@luzfcb: https://github.com/luzfcb
.. _@theskumar: https://github.com/theskumar
.. _@audreyr: https://github.com/audreyr
.. _@jayfk: https://github.com/jayfk
Other Contributors
-------------------
Listed in alphabetical order.
========================== ============================ ==============
Name Github Twitter
========================== ============================ ==============
a7p `@a7p`_
Aaron Eikenberry `@aeikenberry`_
Adam Bogdał `@bogdal`_
Adam Dobrawy `@ad-m`_
Agam Dua
Alberto Sanchez `@alb3rto`_
Alex Tsai `@caffodian`_
Alvaro [Andor] `@andor-pierdelacabeza`_
Amjith Ramanujam `@amjith`_
Andrew Mikhnevich `@zcho`_
Andy Rose
Anna Callahan `@jazztpt`_
Areski Belaid `@areski`_
Ashley Camba
Barclay Gauld `@yunti`_
Ben Lopatin
Benjamin Abel
Bouke Haarsma
Burhan Khalid `@burhan`_ @burhan
Catherine Devlin `@catherinedevlin`_
Chris Curvey `@ccurvey`_
Chris Franklin
Chris Franklin `@hairychris`_
Chris Pappalardo `@ChrisPappalardo`_
Collederas `@Collederas`_
Cristian Vargas `@cdvv7788`_
Cullen Rhodes `@c-rhodes`_
Daniele Tricoli `@eriol`_
David Díaz `@ddiazpinto`_ @DavidDiazPinto
Davur Clementsen `@dsclementsen`_ @davur
Eraldo Energy `@eraldo`_
Eyad Al Sibai `@eyadsibai`_
Felipe Arruda `@arruda`_
Garry Cairns `@garry-cairns`_
Garry Polley `@garrypolley`_
Harry Percival `@hjwp`_
Henrique G. G. Pereira `@ikkebr`_
Ian Lee `@IanLee1521`_
Jan Van Bruggen `@jvanbrug`_
Julio Castillo `@juliocc`_
Kaido Kert `@kaidokert`_
Kaveh `@ka7eh`_
Kevin A. Stone
Kevin Ndung'u `@kevgathuku`_
Lin Xianyi `@iynaix`_
Luis Nell `@originell`_
Lukas Klein
Lyla Fischer
Martin Blech
Mathijs Hoogland `@MathijsHoogland`_
Matt Linares
Matt Menzenski `@menzenski`_
Matt Warren `@mfwarren`_
mozillazg `@mozillazg`_
Pablo `@oubiga`_
Raphael Pierzina `@hackebrot`_
Roman Afanaskin `@siauPatrick`_
Russell Davies
stepmr `@stepmr`_
Sławek Ehlert `@slafs`_
Taylor Baldwin
Théo Segonds `@show0k`_
Tom Atkins `@knitatoms`_
Tom Offermann
Travis McNeill `@Travistock`_ @tavistock_esq
Vitaly Babiy
Yaroslav Halchenko
========================== ============================ ==============
.. _@a7p: https://github.com/a7p
.. _@ad-m: https://github.com/ad-m
.. _@aeikenberry: https://github.com/aeikenberry
.. _@alb3rto: https://github.com/alb3rto
.. _@amjith: https://github.com/amjith
.. _@andor-pierdelacabeza: https://github.com/andor-pierdelacabeza
.. _@areski: https://github.com/areski
.. _@arruda: https://github.com/arruda
.. _@bogdal: https://github.com/bogdal
.. _@burhan: https://github.com/burhan
.. _@c-rhodes: https://github.com/c-rhodes
.. _@caffodian: https://github.com/caffodian
.. _@catherinedevlin: https://github.com/catherinedevlin
.. _@ccurvey: https://github.com/ccurvey
.. _@cdvv7788: https://github.com/cdvv7788
.. _@ChrisPappalardo: https://github.com/ChrisPappalardo
.. _@Collederas: https://github.com/Collederas
.. _@ddiazpinto: https://github.com/ddiazpinto
.. _@eraldo: https://github.com/eraldo
.. _@eriol: https://github.com/eriol
.. _@eyadsibai: https://github.com/eyadsibai
.. _@garry-cairns: https://github.com/garry-cairns
.. _@garrypolley: https://github.com/garrypolley
.. _@hackebrot: https://github.com/hackebrot
.. _@hairychris: https://github.com/hairychris
.. _@hjwp: https://github.com/hjwp
.. _@IanLee1521: https://github.com/IanLee1521
.. _@ikkebr: https://github.com/ikkebr
.. _@iynaix: https://github.com/iynaix
.. _@jazztpt: https://github.com/jazztpt
.. _@juliocc: https://github.com/juliocc
.. _@jvanbrug: https://github.com/jvanbrug
.. _@ka7eh: https://github.com/ka7eh
.. _@kaidokert: https://github.com/kaidokert
.. _@kevgathuku: https://github.com/kevgathuku
.. _@knitatoms: https://github.com/knitatoms
.. _@MathijsHoogland: https://github.com/MathijsHoogland
.. _@menzenski: https://github.com/menzenski
.. _@mfwarren: https://github.com/mfwarren
.. _@mozillazg: https://github.com/mozillazg
.. _@originell: https://github.com/originell
.. _@oubiga: https://github.com/oubiga
.. _@show0k: https://github.com/show0k
.. _@siauPatrick: https://github.com/siauPatrick
.. _@slafs: https://github.com/slafs
.. _@stepmr: https://github.com/stepmr
.. _@Travistock: https://github.com/Tavistock
.. _@yunti: https://github.com/yunti
.. _@zcho: https://github.com/zcho
Special Thanks
~~~~~~~~~~~~~~
The following haven't provided code directly, but have provided guidance and advice.
* Jannis Leidel
* Nate Aune
* Barry Morrison

View File

@ -1,63 +0,0 @@
Code Contributors
=================
Daniel Greenfeld*
a7p
Lukas Klein
Ben Lopatin
Bouke Haarsma
Agam Dua
Vitaly Babiy
Jim Munro*
Tom Offermann
Lyla Fischer
Taylor Baldwin
Chris Curvey (@ccurvey)
Fábio C. Barrionuevo da Luz (@luzfcb)*
Saurabh Kumar (gh: theskumar / @_theskumar)*
Ashley Camba
Yaroslav Halchenko
Pablo / @oubiga
Tom Atkins / @knitatoms
Julio Castillo / @juliocc
Kevin A. Stone
mozillazg / @mozillazg
Henrique G. G. Pereira / @ikkebr
Travis McNeill / gh: Tavistock / @tavistock_esq
Matt Linares
Russell Davies
Sławek Ehlert / @slafs
Alberto Sanchez / @alb3rto
Eyad Al Sibai / @eyadsibai
Chris Franklin
Benjamin Abel
Felipe Arruda / @arruda
Matt Warren / @mfwarren
Martin Blech
Andy Rose
Andrew Mikhnevich / @zcho
Kevin Ndung'u / @kevgathuku
Kaveh / @ka7eh
Alex Tsai / @caffodian
Garry Cairns / @garry-cairns
Lin Xianyi / @iynaix
Adam Dobrawy / @ad-m
Daniele Tricoli / @eriol
Harry Percival / @hjwp
Cullen Rhodes / @c-rhodes
Burhan Khalid / @burhan
Audrey Roy Greenfeld / @audreyr (and creator/maintainer of cookiecutter) *
Jannis Gebauer / @got_nil
jayfk / @jayfk
stepmr / @stepmr
* Possesses commit rights
Special Thanks
==============
The following haven't provided code directly, but have provided guidance and advice.
Jannis Leidel (django-configurations)
Nate Aune
Barry Morrison

View File

@ -13,33 +13,44 @@ cookiecutter-django
:target: https://gitter.im/pydanny/cookiecutter-django?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
A cookiecutter_ template for Django.
A Cookiecutter_ template for Django.
.. _cookiecutter: https://github.com/audreyr/cookiecutter
Features
---------
* For Django 1.8
* Renders Django projects with 100% test coverage
* Twitter Bootstrap_ 3
* For Django 1.9
* Renders Django projects with 100% starting test coverage
* Twitter Bootstrap_ v4.0.0 - alpha_
* End-to-end via Hitch_
* AngularJS_
* 12-Factor_ based settings via django-environ_
* Optimized development and production settings
* Registration via django-allauth_
* Procfile_ for deploying to Heroku
* Works great with Dokku
* Comes with custom user model ready to go.
* Grunt build for compass and livereload
* Basic e-mail configurations for sending emails via Mailgun_
* Media storage using Amazon S3
* Serve static files from Amazon S3 or Whitenoise_ (optional)
* Pre configured Celery_ (optional)
* Integration with Maildump_ for local email testing (optional)
* Integration with Sentry_ for error logging (optional)
* Docker support using docker-compose_ for dev (with debug) and prod (optional)
* PyCharm "Run/Debug Configurations" for django, grunt and docker (optional)
* Docker support using docker-compose_ for development and production
* Procfile_ for deploying to Heroku
* Works with Python 2.7.x or 3.5.x!
* Run tests with unittest or py.test!
Optional Integrations
---------------------
*These features can be enabled during initial project setup.*
* Serve static files from Amazon S3 or Whitenoise_
* Configuration for Celery_
* Integration with MailHog_ for local email testing
* Integration with Sentry_ for error logging
* Integration with NewRelic_ for performance monitoring
* Integration with Opbeat_ for performance monitoring
.. _alpha: http://blog.getbootstrap.com/2015/08/19/bootstrap-4-alpha/
.. _Hitch: https://github.com/hitchtest/hitchtest
.. _Bootstrap: https://github.com/twbs/bootstrap
.. _AngularJS: https://github.com/angular/angular.js
@ -51,9 +62,11 @@ Features
.. _Mailgun: https://mailgun.com/
.. _Whitenoise: https://whitenoise.readthedocs.org/
.. _Celery: http://www.celeryproject.org/
.. _Maildump: https://github.com/ThiefMaster/maildump
.. _MailHog: https://github.com/mailhog/MailHog
.. _Sentry: https://getsentry.com
.. _NewRelic: https://newrelic.com
.. _docker-compose: https://www.github.com/docker/compose
.. _Opbeat: https://opbeat.com/
Constraints
@ -83,6 +96,8 @@ You'll be prompted for some questions, answer them, then it will create a Django
**Warning**: After this point, change 'Daniel Greenfeld', 'pydanny', etc to your own information.
**Warning**: repo_name must be a valid Python module name or you will have issues on imports.
It prompts you for questions. Answer them::
Cloning into 'cookiecutter-django'...
@ -91,22 +106,33 @@ It prompts you for questions. Answer them::
remote: Total 550 (delta 283), reused 479 (delta 222)
Receiving objects: 100% (550/550), 127.66 KiB | 58 KiB/s, done.
Resolving deltas: 100% (283/283), done.
project_name (default is "project_name")? Reddit Clone
repo_name (default is "Reddit_Clone")? reddit
author_name (default is "Your Name")? Daniel Greenfeld
email (default is "Your email")? pydanny@gmail.com
description (default is "A short description of the project.")? A reddit clone.
domain_name (default is "example.com")? myreddit.com
version (default is "0.1.0")? 0.0.1
timezone (default is "UTC")?
now (default is "2015/01/13")? 2015/01/16
year (default is "2015")?
use_whitenoise (default is "y")?
project_name [project_name]: Reddit Clone
repo_name [Reddit_Clone]: reddit
author_name [Your Name]: Daniel Greenfeld
email [Your email]: pydanny@gmail.com
description [A short description of the project.]: A reddit clone.
domain_name [example.com]: myreddit.com
version [0.1.0]: 0.0.1
timezone [UTC]:
now [2016/03/01]: 2016/03/05
year [2015]:
use_whitenoise [y]: n
use_celery [n]: y
use_mailhog [n]: n
use_sentry [n]: y
use_newrelic [n]: y
use_opbeat [n]: y
windows [n]: n
use_python2 [n]: y
Select open_source_license:
1 - MIT
2 - BSD
3 - Not open source
Choose from 1, 2, 3 [1]: 1
Enter the project and take a look around::
$ cd redditclone/
$ cd reddit/
$ ls
Create a GitHub repo and push it there::
@ -119,107 +145,33 @@ Create a GitHub repo and push it there::
Now take a look at your repo. Don't forget to carefully look at the generated README. Awesome, right?
Getting up and running
----------------------
For development, see the following for local development:
The steps below will get you up and running with a local development environment. We assume you have the following installed:
* `Developing locally`_
* `Developing locally using docker`_
* pip
* virtualenv
* PostgreSQL
.. _`Developing locally`: http://cookiecutter-django.readthedocs.org/en/latest/developing-locally.html
.. _`Developing locally using docker`: http://cookiecutter-django.readthedocs.org/en/latest/developing-locally-docker.html
First make sure to create and activate a virtualenv_, then open a terminal at the project root and install the requirements for local development::
Articles
---------
$ pip install -r requirements/local.txt
* `Development and Deployment of Cookiecutter-Django via Docker`_
* `Development and Deployment of Cookiecutter-Django on Fedora`_
.. _virtualenv: http://docs.python-guide.org/en/latest/dev/virtualenvs/
.. _`Development and Deployment of Cookiecutter-Django via Docker`: https://realpython.com/blog/python/development-and-deployment-of-cookiecutter-django-via-docker
.. _`Development and Deployment of Cookiecutter-Django on Fedora`: https://realpython.com/blog/python/development-and-deployment-of-cookiecutter-django-on-fedora/
Then, create a PostgreSQL database and add the database configuration using the ``dj-database-url`` app pattern: ``postgres://db_owner:password@dbserver_ip:port/db_name`` either:
Support This Project
---------------------------
* in the ``config.settings.common.py`` setting file,
* or in the environment variable ``DATABASE_URL``
This project is maintained by volunteers. Support their efforts by spreading the word about:
You can now run the usual Django ``migrate`` and ``runserver`` command::
$ python manage.py migrate
$ python manage.py runserver
**Live reloading and Sass CSS compilation**
If you'd like to take advantage of live reloading and Sass / Compass CSS compilation you can do so with the included Grunt task.
Make sure that nodejs_ is installed. Then in the project root run::
$ npm install
.. _nodejs: http://nodejs.org/download/
Now you just need::
$ grunt serve
The base app will now run as it would with the usual ``manage.py runserver`` but with live reloading and Sass compilation enabled.
To get live reloading to work you'll probably need to install an `appropriate browser extension`_
.. _appropriate browser extension: http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-
It's time to write the code!!!
Getting up and running using docker
----------------------------------
The steps below will get you up and running with a local development environment. We assume you have the following installed:
* docker
* docker-compose
Open a terminal at the project root and run the following for local development::
$ docker-compose -f dev.yml up
You can also set the environment variable ``COMPOSE_FILE`` pointing to ``dev.yml`` like this::
$ export COMPOSE_FILE=dev.yml
And then run::
$ docker-compose up
If you want to connect to python interpreter inside docker container with remote debbuger, you have to run different
container with debug.yml (dev.yml has to be build first)::
$ docker-compose -f dev.yml build; docker-compose -f debug.yml up
See `docker remote debugging instructions <{{cookiecutter.repo_name}}/docs/docker_remote_debugging.rst>`_ for particular IDE (PyCharm, etc).
To migrate your app and to create a superuser, run::
$ docker-compose run django python manage.py migrate
$ docker-compose run django python manage.py createsuperuser
If you are using `boot2docker` to develop on OS X or Windows, you need to create a `/data` partition inside your boot2docker
vm to make all changes persistent. If you don't do that your `/data` directory will get wiped out on every reboot.
To create a persistent folder, log into the `boot2docker` vm by running::
$ bootdocker ssh
And then::
$ sudo su
$ echo 'ln -sfn /mnt/sda1/data /data' >> /var/lib/boot2docker/bootlocal.sh
In case you are wondering why you can't use a host volume to keep the files on your mac: As of `boot2docker` 1.7 you'll
run into permission problems with mounted host volumes if the container creates his own user and `chown`s the directories
on the volume. Postgres is doing that, so we need this quick fix to ensure that all development data persists.
.. image:: https://s3.amazonaws.com/tsacademy/images/tsa-logo-250x60-transparent-01.png
:name: Two Scoops Academy
:align: center
:alt: Two Scoops Academy
:target: http://www.twoscoops.academy/
For Readers of Two Scoops of Django 1.8
--------------------------------------------

View File

@ -1,18 +1,22 @@
{
"project_name": "project_name",
"repo_name": "{{ cookiecutter.project_name|replace(' ', '_') }}",
"repo_name": "{{ cookiecutter.project_name|replace(' ', '_')|replace('-', '_') }}",
"author_name": "Your Name",
"email": "Your email",
"description": "A short description of the project.",
"domain_name": "example.com",
"version": "0.1.0",
"timezone": "UTC",
"now": "2015/01/13",
"now": "2016/03/05",
"year": "{{ cookiecutter.now[:4] }}",
"use_whitenoise": "y",
"use_celery": "n",
"use_maildump": "n",
"use_mailhog": "n",
"use_sentry": "n",
"use_newrelic": "n",
"use_opbeat": "n",
"use_pycharm": "n",
"windows": "n"
"windows": "n",
"use_python2": "n",
"open_source_license": ["MIT", "BSD", "Not open source"]
}

153
docs/Makefile Normal file
View File

@ -0,0 +1,153 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/{{ cookiecutter.repo_name }}.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/{{ cookiecutter.repo_name }}.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/{{ cookiecutter.repo_name }}"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/{{ cookiecutter.repo_name }}"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

1
docs/__init__.py Normal file
View File

@ -0,0 +1 @@
# Included so that Django's startproject comment runs against the docs directory

247
docs/conf.py Normal file
View File

@ -0,0 +1,247 @@
# -*- coding: utf-8 -*-
#
# cookiecutter-django documentation build configuration file.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
from datetime import datetime
import os
import sys
now = datetime.now()
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'cookiecutter-django'
copyright = u"2013-{}, Daniel Roy Greenfeld".format(now.year)
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '{}.{}.{}'.format(*now.isocalendar())
# The full version, including alpha/beta/rc tags.
release = '{}.{}.{}'.format(*now.isocalendar())
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
# html_additional_pages = {}
# If false, no module index is generated.
# html_domain_indices = True
# If false, no index is generated.
# html_use_index = True
# If true, the index is split into individual pages for each letter.
# html_split_index = False
# If true, links to the reST sources are added to the pages.
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'cookiecutter-djangodoc'
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
# 'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index',
'cookiecutter-django.tex',
u'cookiecutter-django Documentation',
u"cookiecutter-django", 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# latex_use_parts = False
# If true, show page references after internal links.
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
# latex_appendices = []
# If false, no module index is generated.
# latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'cookiecutter-django', u'cookiecutter-django documentation',
[u"Daniel Roy Greenfeld"], 1)
]
# If true, show URL addresses after external links.
# man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'cookiecutter-django', u'cookiecutter-django documentation',
u"Daniel Roy Greenfeld", 'cookiecutter-django',
'A Cookiecutter template for creating production-ready Django projects quickly.', 'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
# texinfo_appendices = []
# If false, no module index is generated.
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
# texinfo_show_urls = 'footnote'

View File

@ -0,0 +1,38 @@
Deployment on 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:
.. code-block:: bash
heroku create --buildpack https://github.com/heroku/heroku-buildpack-python
heroku addons:create heroku-postgresql:hobby-dev
heroku pg:backups schedule --at '02:00 America/Los_Angeles' DATABASE_URL
heroku pg:promote DATABASE_URL
heroku addons:create heroku-redis:hobby-dev
heroku addons:create mailgun
heroku config:set DJANGO_ADMIN_URL=`openssl rand -base64 32`
heroku config:set DJANGO_SECRET_KEY=`openssl rand -base64 64`
heroku config:set DJANGO_SETTINGS_MODULE='config.settings.production'
heroku config:set DJANGO_ALLOWED_HOSTS='.herokuapp.com'
heroku config:set DJANGO_AWS_ACCESS_KEY_ID=YOUR_AWS_ID_HERE
heroku config:set DJANGO_AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_ACCESS_KEY_HERE
heroku config:set DJANGO_AWS_STORAGE_BUCKET_NAME=YOUR_AWS_S3_BUCKET_NAME_HERE
heroku config:set DJANGO_MAILGUN_SERVER_NAME=YOUR_MALGUN_SERVER
heroku config:set DJANGO_MAILGUN_API_KEY=YOUR_MAILGUN_API_KEY
heroku config:set PYTHONHASHSEED=random
heroku config:set DJANGO_ADMIN_URL=\^somelocation/
git push heroku master
heroku run python manage.py migrate
heroku run python manage.py check --deploy
heroku run python manage.py createsuperuser
heroku open

View File

@ -0,0 +1,112 @@
Deployment with Docker
=================================================
.. index:: Docker, deployment
TODO: Review and revise
**Warning**
Docker is evolving extremely fast, but it has still some rough edges here and there. Compose is currently (as of version 1.4)
not considered production ready. That means you won't be able to scale to multiple servers and you won't be able to run
zero downtime deployments out of the box. Consider all this as experimental until you understand all the implications
to run docker (with compose) on production.
**Run your app with docker-compose**
Prerequisites:
* docker (at least 1.10)
* docker-compose (at least 1.6)
Before you start, check out the `docker-compose.yml` file in the root of this project. This is where each component
of this application gets its configuration from. It consists of a `postgres` service that runs the database, `redis`
for caching, `nginx` as reverse proxy and last but not least the `django` application run by gunicorn.
{% if cookiecutter.use_celery == 'y' -%}
Since this application also runs Celery, there are two more services with a service called `celeryworker` that runs the
celery worker process and `celerybeat` that runs the celery beat process.
{% endif %}
All of these services except `redis` rely on environment variables set by you. There is an `env.example` file in the
root directory of this project as a starting point. Add your own variables to the file and rename it to `.env`. This
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.
By default, the application is configured to listen on all interfaces on port 80. If you want to change that, open the
`docker-compose.yml` file and replace `0.0.0.0` with your own ip. If you are using `nginx-proxy`_ to run multiple
application stacks on one host, remove the port setting entirely and add `VIRTUAL_HOST={{cookiecutter.domain_name}}` to your env file.
This pass all incoming requests on `nginx-proxy`_ to the nginx service your application is using.
.. _nginx-proxy: https://github.com/jwilder/nginx-proxy
Postgres is saving its database files to `/data/{{cookiecutter.repo_name}}/postgres` by default. Change that if you wan't
something else and make sure to make backups since this is not done automatically.
To get started, pull your code from source control (don't forget the `.env` file) and change to your projects root
directory.
You'll need to build the stack first. To do that, run::
docker-compose build
Once this is ready, you can run it with::
docker-compose up
To run a migration, open up a second terminal and run::
docker-compose run django python manage.py migrate
To create a superuser, run::
docker-compose run django python manage.py createsuperuser
If you need a shell, run::
docker-compose run django python manage.py shell
To get an output of all running containers.
To check your logs, run::
docker-compose logs
If you want to scale your application, run::
docker-compose scale django=4
docker-compose scale celeryworker=2
**Don't run the scale command on postgres or celerybeat**
Once you are ready with your initial setup, you wan't 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
it needs to do is to run `docker-compose up` in your projects root directory.
If you are using `supervisor`, you can use this file as a starting point::
[program:{{cookiecutter.repo_name}}]
command=docker-compose up
directory=/path/to/{{cookiecutter.repo_name}}
redirect_stderr=true
autostart=true
autorestart=true
priority=10
Place it in `/etc/supervisor/conf.d/{{cookiecutter.repo_name}}.conf` and run::
supervisorctl reread
supervisorctl start {{cookiecutter.repo_name}}
To get the status, run::
supervisorctl status
If you have errors, you can always check your stack with `docker-compose`. Switch to your projects root directory and run::
docker-compose ps

View File

@ -0,0 +1,137 @@
Getting Up and Running with Docker
==================================
.. index:: Docker
The steps below will get you up and running with a local development environment.
All of these commands assume you are in the root of your generated project.
Prerequisites
-------------
You'll need at least docker 1.10.
If you don't already have it installed, follow the instructions for your OS:
- On Mac OS X/Windows, you'll need `Docker Toolbox`_
- On Linux, you'll need `docker-engine`_
.. _`Docker Toolbox`: https://github.com/docker/toolbox/releases
.. _`docker-engine`: https://docs.docker.com/engine/installation/
Create the Machine (Optional)
-----------------------------
On Linux you have native Docker, so you don't need to create a VM with
docker-machine to use it.
However, on Mac/Windows/other systems without native Docker, you'll want to
start by creating a VM with docker-machine::
$ docker-machine create --driver virtualbox dev1
**Note:** If you want to have more than one docker development environment, then
name them accordingly. Instead of 'dev1' you might have 'dev2', 'myproject',
'djangopackages', et al.
Get the IP Address
------------------
Once your machine is up and running, run this::
$ docker-machine ip dev1
123.456.789.012
This is also the IP address where the Django project will be served from.
Build the Stack
---------------
This can take a while, especially the first time you run this particular command
on your development system::
$ docker-compose -f dev.yml build
If you want to build the production environment you don't have to pass an argument -f, it will automatically use docker-compose.yml.
Boot the System
---------------
This brings up both Django and PostgreSQL.
The first time it is run it might take a while to get started, but subsequent
runs will occur quickly.
Open a terminal at the project root and run the following for local development::
$ docker-compose -f dev.yml up
You can also set the environment variable ``COMPOSE_FILE`` pointing to ``dev.yml`` like this::
$ export COMPOSE_FILE=dev.yml
And then run::
$ docker-compose up
Running management commands
~~~~~~~~~~~~~~~~~~~~~~~~~~~
As with any shell command that we wish to run in our container, this is done
using the ``docker-compose run`` command.
To migrate your app and to create a superuser, run::
$ docker-compose -f dev.yml run django python manage.py migrate
$ docker-compose -f dev.yml run django python manage.py createsuperuser
Here we specify the ``django`` container as the location to run our management commands.
Production Mode
~~~~~~~~~~~~~~~
Instead of using `dev.yml`, you would use `docker-compose.yml`.
Database Backups
~~~~~~~~~~~~~~~~
The database has to be running to create/restore a backup.
First, run the app with `docker-compose -f dev.yml up`.
To create a backup, run::
docker-compose -f dev.yml run postgres backup
To list backups, run::
docker-compose -f dev.yml run postgres list-backups
To restore a backup, run::
docker-compose -f dev.yml run postgres restore filename.sql
Other Useful Tips
-----------------
Make a machine the active unit
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This tells our computer that all future commands are specifically for the dev1 machine.
Using the ``eval`` command we can switch machines as needed.
::
$ eval "$(docker-machine env dev1)"
Detached Mode
~~~~~~~~~~~~~
If you want to run the stack in detached mode (in the background), use the ``-d`` argument:
::
$ docker-compose -f dev.yml up -d

View File

@ -0,0 +1,80 @@
Getting Up and Running Locally
==============================
.. index:: pip, virtualenv, PostgreSQL
The steps below will get you up and running with a local development environment. We assume you have the following installed:
* pip
* virtualenv
* PostgreSQL
First make sure to create and activate a virtualenv_, then open a terminal at the project root and install the os dependencies::
$ sudo ./install_os_dependencies.sh install
Then install the requirements for your local development::
$ pip install -r requirements/local.txt
.. _virtualenv: http://docs.python-guide.org/en/latest/dev/virtualenvs/
Then, create a PostgreSQL database with the following command, where `[repo_name]` is what value you entered for your project's `repo_name`::
$ createdb [repo_name]
`cookiecutter-django` uses the excellent `django-environ`_ package with its ``DATABASE_URL`` environment variable to simplify database configuration in your Django settings. Now all you have to do is compose a definition for ``DATABASE_URL``:
.. parsed-literal::
$ export DATABASE_URL="postgres://*<pg_user_name>*:*<pg_user_password>*\ @127.0.0.1:\ *<pg_port>*/*<pg_database_name>*"
.. _django-environ: http://django-environ.readthedocs.org
You can now run the usual Django ``migrate`` and ``runserver`` commands::
$ python manage.py migrate
$ python manage.py runserver
**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`_
.. _configure your email backend: http://docs.djangoproject.com/en/1.9/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::
1. `Download the latest release`_ for your operating system
2. Rename the executable to ``mailhog`` and copy it to the root of your project directory
3. Make sure it is executable (e.g. ``chmod +x mailhog``)
.. _Mailhog: https://github.com/mailhog/MailHog/
.. _Download the latest release: https://github.com/mailhog/MailHog/releases
Alternatively simply output emails to the console via: ``EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'``
In production basic email configuration is setup to send emails with Mailgun_
.. _Mailgun: https://www.mailgun.com/
**Live reloading and Sass CSS compilation**
If you'd like to take advantage of live reloading and Sass / Compass CSS compilation you can do so with the included Grunt task.
Make sure that nodejs_ is installed. Then in the project root run::
$ npm install
.. _nodejs: http://nodejs.org/download/
Now you just need::
$ grunt serve
The base app will now run as it would with the usual ``manage.py runserver`` but with live reloading and Sass compilation enabled.
To get live reloading to work you'll probably need to install an `appropriate browser extension`_
.. _appropriate browser extension: http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-
It's time to write the code!!!

27
docs/faq.rst Normal file
View File

@ -0,0 +1,27 @@
FAQ
====
.. index:: FAQ, 12-Factor App
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.
See `0002_set_site_domain_and_name.py`_.
.. _`0002_set_site_domain_and_name.py`: https://github.com/pydanny/cookiecutter-django/blob/master/%7B%7Bcookiecutter.repo_name%7D%7D/%7B%7Bcookiecutter.repo_name%7D%7D/contrib/sites/migrations/0002_set_site_domain_and_name.py
Why aren't you using just one configuration file (12-Factor App)
----------------------------------------------------------------------
TODO
Why doesn't this follow the layout from 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 of `Two Scoops of Django`_. The reason for that is this project, amongst other things, serves as a test bed for trying out new ideas and concepts. Sometimes they work, sometimes they don't, but the end result is that it won't necessarily match precisely what is described in the book I co-authored.
.. _`Two Scoops of Django`: http://twoscoopspress.com/products/two-scoops-of-django-1-8

35
docs/index.rst Normal file
View File

@ -0,0 +1,35 @@
.. cookiecutter-django documentation master file.
Welcome to cookiecutter-django's documentation!
====================================================================
A Cookiecutter_ template for Django.
.. _cookiecutter: https://github.com/audreyr/cookiecutter
.. note:: This is an in-progress documentation reorganization. Locations of files may change dramatically over the course of the next few days. See https://github.com/pydanny/cookiecutter-django/issues/335
Contents:
.. toctree::
:maxdepth: 2
project-generation-options
developing-locally
developing-locally-docker
settings
linters
live-reloading-and-sass-compilation
deployment-on-heroku
deployment-with-docker
faq
Indices and tables
==================
* :ref:`genindex`
* :ref:`search`
.. At some point it would be good to have a module index of the high level things
we are doing. Then we can * :ref:`modindex` back in.

43
docs/linters.rst Normal file
View File

@ -0,0 +1,43 @@
Linters
=======
.. index:: linters
flake8
-------
To run flake8:
$ flake8
The config for flake8 is located in setup.cfg. It specifies:
* Set max line length to 120 chars
* Exclude .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules
pylint
------
This is included in flake8's checks, but you can also run it separately to see a more detailed report:
$ pylint <python files that you wish to lint>
The config for pylint is located in .pylintrc. It specifies:
* Use the pylint_common and pylint_django plugins. If using Celery, also use pylint_celery.
* Set max line length to 120 chars
* Disable linting messages for missing docstring and invalid name
* max-parents=13
pep8
-----
This is included in flake8's checks, but you can also run it separately to see a more detailed report:
$ pep8 <python files that you wish to lint>
The config for pep8 is located in setup.cfg. It specifies:
* Set max line length to 120 chars
* Exclude .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules

View File

@ -0,0 +1,24 @@
Live reloading and Sass CSS compilation
=======================================
If you'd like to take advantage of live reloading and Sass / Compass CSS compilation you can do so with a little bit of prep work.
Make sure that nodejs_ is installed. Then in the project root run::
$ npm install
.. _nodejs: http://nodejs.org/download/
If you don't already have it, install `compass` (doesn't hurt if you run this command twice)::
gem install compass
Now you just need::
$ grunt serve
The base app will now run as it would with the usual ``manage.py runserver`` but with live reloading and Sass compilation enabled.
To get live reloading to work you'll probably need to install an `appropriate browser extension`_
.. _appropriate browser extension: http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-

190
docs/make.bat Normal file
View File

@ -0,0 +1,190 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\{{ cookiecutter.repo_name }}.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\{{ cookiecutter.repo_name }}.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end

View File

@ -0,0 +1,55 @@
Project Generation Options
==========================
project_name [project_name]:
Your human-readable project name, including any capitalization or spaces.
repo_name [project_name]:
The slug of your project, without dashes or spaces. Used to name your repo
and in other places where a Python-importable version of your project name
is needed.
author_name [Your Name]:
You! This goes into places like the LICENSE file.
email [Your email]:
Your email address.
description [A short description of the project.]
Used in the generated README.rst and other places.
domain_name [example.com]
Whatever domain name you plan to use for your project when it goes live.
version [0.1.0]
The starting version number for your project.
timezone [UTC]
Used in the common settings file for the `TIME_ZONE` value.
use_whitenoise [y]
Whether to use WhiteNoise_ for static file serving.
use_celery [n]
Whether to use Celery_. This gives you the ability to use distributed task
queues in your project.
use_mailhog [n]
Whether to use MailHog_. MailHog is a tool that simulates email receiving
for development purposes. It runs a simple SMTP server which catches
any message sent to it. Messages are displayed in a web interface which runs at ``http://localhost:8025/`` You need to download the MailHog executable for your operating system, see the 'Developing Locally' docs for instructions.
use_sentry [n]
Whether to use Sentry_ to log errors from your project.
windows [n]
Whether you'll be developing on Windows.
use_python2 [n]
By default, the Python code generated will be for Python 3.x. But if you
answer `y` here, it will be legacy Python 2.7 code.
.. _WhiteNoise: https://github.com/evansd/whitenoise
.. _Celery: https://github.com/celery/celery
.. _MailHog: https://github.com/mailhog/MailHog
.. _Sentry: https://github.com/getsentry/sentry

55
docs/settings.rst Normal file
View File

@ -0,0 +1,55 @@
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.
For configuration purposes, the following table maps environment variables to their Django setting:
======================================= =========================== ============================================== ======================================================================
Environment Variable Django Setting Development Default Production Default
======================================= =========================== ============================================== ======================================================================
DJANGO_ADMIN_URL n/a r'^admin/' raises error
DJANGO_CACHES CACHES (default) locmem redis
DJANGO_DATABASES DATABASES (default) See code See code
DJANGO_DEBUG DEBUG True False
DJANGO_SECRET_KEY SECRET_KEY CHANGEME!!! raises error
DJANGO_SECURE_BROWSER_XSS_FILTER SECURE_BROWSER_XSS_FILTER n/a True
DJANGO_SECURE_SSL_REDIRECT SECURE_SSL_REDIRECT n/a True
DJANGO_SECURE_CONTENT_TYPE_NOSNIFF SECURE_CONTENT_TYPE_NOSNIFF n/a True
DJANGO_SECURE_FRAME_DENY SECURE_FRAME_DENY n/a True
DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS HSTS_INCLUDE_SUBDOMAINS n/a True
DJANGO_SESSION_COOKIE_HTTPONLY SESSION_COOKIE_HTTPONLY n/a True
DJANGO_SESSION_COOKIE_SECURE SESSION_COOKIE_SECURE n/a False
DJANGO_DEFAULT_FROM_EMAIL DEFAULT_FROM_EMAIL n/a "your_project_name <noreply@your_domain_name>"
DJANGO_SERVER_EMAIL SERVER_EMAIL n/a "your_project_name <noreply@your_domain_name>"
DJANGO_EMAIL_SUBJECT_PREFIX EMAIL_SUBJECT_PREFIX n/a "[your_project_name] "
DJANGO_ALLOWED_HOSTS ALLOWED_HOSTS ['*'] ['your_domain_name']
======================================= =========================== ============================================== ======================================================================
The following table lists settings and their defaults for third-party applications, which may or may not be part of your project:
======================================= =========================== ============================================== ======================================================================
Environment Variable Django Setting Development Default Production Default
======================================= =========================== ============================================== ======================================================================
DJANGO_AWS_ACCESS_KEY_ID AWS_ACCESS_KEY_ID n/a raises error
DJANGO_AWS_SECRET_ACCESS_KEY AWS_SECRET_ACCESS_KEY n/a raises error
DJANGO_AWS_STORAGE_BUCKET_NAME AWS_STORAGE_BUCKET_NAME n/a raises error
DJANGO_SENTRY_DSN SENTRY_DSN n/a raises error
DJANGO_SENTRY_CLIENT SENTRY_CLIENT n/a raven.contrib.django.raven_compat.DjangoClient
DJANGO_SENTRY_LOG_LEVEL SENTRY_LOG_LEVEL n/a logging.INFO
DJANGO_MAILGUN_API_KEY MAILGUN_ACCESS_KEY n/a raises error
DJANGO_MAILGUN_SERVER_NAME MAILGUN_SERVER_NAME n/a raises error
NEW_RELIC_APP_NAME NEW_RELIC_APP_NAME n/a raises error
NEW_RELIC_LICENSE_KEY NEW_RELIC_LICENSE_KEY n/a raises error
DJANGO_OPBEAT_APP_ID OPBEAT['APP_ID'] n/a raises error
DJANGO_OPBEAT_SECRET_TOKEN OPBEAT['SECRET_TOKEN'] n/a raises error
DJANGO_OPBEAT_ORGANIZATION_ID OPBEAT['ORGANIZATION_ID'] n/a raises error
======================================= =========================== ============================================== ======================================================================
--------------------------
Other Environment Settings
--------------------------
DJANGO_ACCOUNT_ALLOW_REGISTRATION (=True)
Allow enable or disable user registration through `django-allauth` without disabling other characteristics like authentication and account management. (Django Setting: ACCOUNT_ALLOW_REGISTRATION)

View File

@ -1,11 +1,133 @@
# -*- coding: utf-8 -*-
"""
Does the following:
1. Generates and saves random secret key
2. Removes the taskapp if celery isn't going to be used
3. Copy files from /docs/ to {{ cookiecutter.repo_name }}/docs/
TODO: this might have to be moved to a pre_gen_hook
A portion of this code was adopted from Django's standard crypto functions and
utilities, specifically:
https://github.com/django/django/blob/master/django/utils/crypto.py
"""
import hashlib
import os
import random
import shutil
project_directory = os.path.realpath(os.path.curdir)
from cookiecutter.config import DEFAULT_CONFIG
# Get the root project directory
PROJECT_DIRECTORY = os.path.realpath(os.path.curdir)
# Use the system PRNG if possible
try:
random = random.SystemRandom()
using_sysrandom = True
except NotImplementedError:
# import warnings
# warnings.warn('A secure pseudo-random number generator is not available '
# 'on your system. Falling back to Mersenne Twister.')
using_sysrandom = False
def get_random_string(
length=50,
allowed_chars='abcdefghijklmnopqrstuvwxyz0123456789!@#%^&*(-_=+)'):
"""
Returns a securely generated random string.
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
"""
if not using_sysrandom:
# This is ugly, and a hack, but it makes things better than
# the alternative of predictability. This re-seeds the PRNG
# using a value that is hard for an attacker to predict, every
# time a random string is required. This may change the
# properties of the chosen random sequence slightly, but this
# is better than absolute predictability.
random.seed(
hashlib.sha256(
("%s%s%s" % (
random.getstate(),
time.time(),
settings.SECRET_KEY)).encode('utf-8')
).digest())
return ''.join(random.choice(allowed_chars) for i in range(length))
def set_secret_key(setting_file_location):
# Open locals.py
with open(setting_file_location) as f:
file_ = f.read()
# Generate a SECRET_KEY that matches the Django standard
SECRET_KEY = get_random_string()
# Replace "CHANGEME!!!" with SECRET_KEY
file_ = file_.replace('CHANGEME!!!', SECRET_KEY, 1)
# Write the results to the locals.py module
with open(setting_file_location, 'w') as f:
f.write(file_)
def make_secret_key(project_directory):
"""Generates and saves random secret key"""
# Determine the local_setting_file_location
local_setting = os.path.join(
project_directory,
'config/settings/local.py'
)
# local.py settings file
set_secret_key(local_setting)
env_file = os.path.join(
project_directory,
'env.example'
)
# env.example file
set_secret_key(env_file)
def remove_task_app(project_directory):
"""Removes the taskapp if celery isn't going to be used"""
# Determine the local_setting_file_location
task_app_location = os.path.join(
PROJECT_DIRECTORY,
'{{ cookiecutter.repo_name }}/taskapp'
)
shutil.rmtree(task_app_location)
# IN PROGRESS
# def copy_doc_files(project_directory):
# cookiecutters_dir = DEFAULT_CONFIG['cookiecutters_dir']
# cookiecutter_django_dir = os.path.join(
# cookiecutters_dir,
# 'cookiecutter-django',
# 'docs'
# )
# target_dir = os.path.join(
# project_directory,
# 'docs'
# )
# for name in os.listdir(cookiecutter_django_dir):
# if name.endswith('.rst') and not name.startswith('index'):
# src = os.path.join(cookiecutter_django_dir, name)
# dst = os.path.join(target_dir, name)
# shutil.copyfile(src, dst)
# 1. Generates and saves random secret key
make_secret_key(PROJECT_DIRECTORY)
# 2. Removes the taskapp if celery isn't going to be used
if '{{ cookiecutter.use_celery }}'.lower() == 'n':
remove_task_app(PROJECT_DIRECTORY)
# 3. Copy files from /docs/ to {{ cookiecutter.repo_name }}/docs/
# copy_doc_files(PROJECT_DIRECTORY)
if '{{cookiecutter.use_pycharm}}' != 'y':
shutil.rmtree(os.path.join(project_directory, '.idea/'))
shutil.rmtree(os.path.join(PROJECT_DIRECTORY, '.idea/'))
docker_private_key = 'compose/debug/keys_to_docker/id_rsa'
os.chmod(os.path.join(project_directory, docker_private_key), 0600)

4
hooks/pre_gen_project.py Normal file
View File

@ -0,0 +1,4 @@
repo_name = '{{ cookiecutter.repo_name }}'
if hasattr(repo_name, 'isidentifier'):
assert repo_name.isidentifier(), 'Repo name should be valid Python identifier!'

View File

@ -1,13 +1,10 @@
cookiecutter==1.0.0
flake8==2.4.1
sh
# Debugging
# -------------------------------------
ipdb==0.8.1
ipython==4.0.0
cookiecutter==1.3.0
flake8==2.5.4
sh==1.11
binaryornot==0.4.0
# Testing
# -------------------------------------
pytest==2.7.2
git+git://github.com/mverteuil/pytest-ipdb.git
pytest==2.9.0
pep8==1.7.0
pyflakes==1.1.0
tox==2.3.1

56
setup.py Normal file
View File

@ -0,0 +1,56 @@
#!/usr/bin/env python
import os
import platform
import sys
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
# Our version ALWAYS matches the version of Django we support
# If Django has a new release, we branch, tag, then update this setting after the tag.
version = "1.9.4"
if sys.argv[-1] == 'tag':
os.system("git tag -a %s -m 'version %s'" % (version, version))
os.system("git push --tags")
sys.exit()
with open('README.rst') as readme_file:
long_description = readme_file.read()
setup(
name='cookiecutter-django',
version=version,
description='A Cookiecutter template for creating production-ready Django projects quickly.',
long_description=long_description,
author='Daniel Roy Greenfeld',
author_email='pydanny@gmail.com',
url='https://github.com/pydanny/cookiecutter-django',
packages=[],
license='BSD',
zip_safe=False,
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: Console',
'Framework :: Django :: 1.9',
'Intended Audience :: Developers',
'Natural Language :: English',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Software Development',
],
keywords=(
'cookiecutter, Python, projects, project templates, django, '
'skeleton, scaffolding, project directory, setup.py'
),
)

View File

View File

@ -1,69 +0,0 @@
import os
import re
import shutil
import unittest
from os.path import exists, dirname, join
import sh
from cookiecutter.main import cookiecutter
class DjangoCookieTestCase(unittest.TestCase):
root_dir = dirname(dirname(__file__))
ctx = {}
destpath = None
def check_paths(self, paths):
"""
Method to check all paths have correct substitutions,
used by other tests cases
"""
# Construct the cookiecutter search pattern
pattern = "{{(\s?cookiecutter)[.](.*?)}}"
re_obj = re.compile(pattern)
# Assert that no match is found in any of the files
for path in paths:
for line in open(path, 'r'):
match = re_obj.search(line)
self.assertIsNone(
match,
"cookiecutter variable not replaced in {}".format(path))
def generate_project(self, extra_context=None):
ctx = {
"project_name": "My Test Project",
"repo_name": "my_test_project",
"author_name": "Test Author",
"email": "test@example.com",
"description": "A short description of the project.",
"domain_name": "example.com",
"version": "0.1.0",
"timezone": "UTC",
"now": "2015/01/13",
"year": "2015"
}
if extra_context:
assert isinstance(extra_context, dict)
ctx.update(extra_context)
self.ctx = ctx
self.destpath = join(self.root_dir, self.ctx['repo_name'])
cookiecutter(template='./', checkout=None, no_input=True, extra_context=ctx)
# Build a list containing absolute paths to the generated files
paths = [os.path.join(dirpath, file_path)
for dirpath, subdirs, files in os.walk(self.destpath)
for file_path in files]
return paths
def clean(self):
if exists(self.destpath):
shutil.rmtree(self.destpath)
sh.cd(self.root_dir)
def tearDown(self):
self.clean()

View File

@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
import os
import re
import sh
import pytest
from binaryornot.check import is_binary
PATTERN = "{{(\s?cookiecutter)[.](.*?)}}"
RE_OBJ = re.compile(PATTERN)
@pytest.fixture
def context():
return {
"project_name": "My Test Project",
"repo_name": "my_test_project",
"author_name": "Test Author",
"email": "test@example.com",
"description": "A short description of the project.",
"domain_name": "example.com",
"version": "0.1.0",
"timezone": "UTC",
"now": "2015/01/13",
"year": "2015"
}
def build_files_list(root_dir):
"""Build a list containing absolute paths to the generated files."""
return [
os.path.join(dirpath, file_path)
for dirpath, subdirs, files in os.walk(root_dir)
for file_path in files
]
def check_paths(paths):
"""Method to check all paths have correct substitutions,
used by other tests cases
"""
# Assert that no match is found in any of the files
for path in paths:
if is_binary(path):
continue
for line in open(path, 'r'):
match = RE_OBJ.search(line)
msg = "cookiecutter variable not replaced in {}"
assert match is None, msg.format(path)
def test_default_configuration(cookies, context):
result = cookies.bake(extra_context=context)
assert result.exit_code == 0
assert result.exception is None
assert result.project.basename == context['repo_name']
assert result.project.isdir()
paths = build_files_list(str(result.project))
assert paths
check_paths(paths)
@pytest.fixture(params=['use_mailhog', 'use_celery', 'windows'])
def feature_context(request, context):
context.update({request.param: 'y'})
return context
def test_enabled_features(cookies, feature_context):
result = cookies.bake(extra_context=feature_context)
assert result.exit_code == 0
assert result.exception is None
assert result.project.basename == feature_context['repo_name']
assert result.project.isdir()
paths = build_files_list(str(result.project))
assert paths
check_paths(paths)
def test_flake8_compliance(cookies):
"""generated project should pass flake8"""
result = cookies.bake()
try:
sh.flake8(str(result.project))
except sh.ErrorReturnCode as e:
pytest.fail(e)

View File

@ -1,33 +0,0 @@
from __future__ import absolute_import
import sh
from .base import DjangoCookieTestCase
class TestCookiecutterSubstitution(DjangoCookieTestCase):
"""Test that all cookiecutter instances are substituted"""
def test_default_configuration(self):
# Build a list containing absolute paths to the generated files
paths = self.generate_project()
self.check_paths(paths)
def test_maildump_enabled(self):
paths = self.generate_project(extra_context={'use_maildump': 'y'})
self.check_paths(paths)
def test_celery_enabled(self):
paths = self.generate_project(extra_context={'use_celery': 'y'})
self.check_paths(paths)
def test_windows_enabled(self):
paths = self.generate_project(extra_context={'windows': 'y'})
self.check_paths(paths)
def test_flake8_compliance(self):
"""generated project should pass flake8"""
self.generate_project()
try:
sh.flake8(self.destpath)
except sh.ErrorReturnCode as e:
raise AssertionError(e)

18
tests/test_docker.sh Normal file
View File

@ -0,0 +1,18 @@
#!/bin/sh
# this is a very simple script that tests the docker configuration for cookiecutter-django
# it is meant to be run from the root directory of the repository, eg:
# sh tests/test_docker.sh
# install test requirements
pip install -r requirements.txt
# create a cache directory
mkdir -p .cache/docker
cd .cache/docker
# create the project using the default settings in cookiecutter.json
cookiecutter ../../ --no-input --overwrite-if-exists
cd project_name
# run the project's tests
docker-compose -f dev.yml run django python manage.py test

12
tox.ini Normal file
View File

@ -0,0 +1,12 @@
[tox]
skipsdist = true
envlist = py27,py34,py35
[testenv]
passenv = LC_ALL, LANG, HOME
deps =
binaryornot
flake8
pytest-cookies
sh
commands = py.test {posargs:tests}

View File

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

View File

@ -0,0 +1,4 @@
.*
!.coveragerc
!.env
!.pylintrc

View File

@ -13,13 +13,12 @@ indent_style = space
indent_size = 4
[*.py]
# https://github.com/timothycrosley/isort/wiki/isort-Settings
line_length=120
known_first_party={{ cookiecutter.repo_name }}
multi_line_output=3
default_section=THIRDPARTY
[*.yml]
[*.{html,css,scss,json,yml}]
indent_style = space
indent_size = 2

View File

@ -21,7 +21,6 @@ sftp-config.json
# Basics
*.py[cod]
*.pyc
__pycache__
# Logs
@ -32,6 +31,7 @@ pip-log.txt
.coverage
.tox
nosetests.xml
htmlcov
# Translations
*.mo
@ -71,3 +71,12 @@ node_modules/
# virtual environments
.env
# User-uploaded media
{{ cookiecutter.repo_name }}/media/
# Hitch directory
tests/.hitch
# MailHog binary
mailhog

View File

@ -0,0 +1,11 @@
[MASTER]
load-plugins=pylint_common, pylint_django{% if cookiecutter.use_celery == "y" %}, pylint_celery {% endif %}
[FORMAT]
max-line-length=120
[MESSAGES CONTROL]
disable=missing-docstring,invalid-name
[DESIGN]
max-parents=13

View File

@ -1,3 +1,4 @@
sudo: true
before_install:
- sudo apt-get update -qq
- sudo apt-get install -qq build-essential gettext python-dev zlib1g-dev libpq-dev xvfb
@ -7,7 +8,11 @@ before_install:
- sudo apt-get install -qq libsqlite3-dev libxml2 libxml2-dev libssl-dev libbz2-dev wget curl llvm
language: python
python:
- "3.4"
{% if cookiecutter.use_python2 == 'n' -%}
- "3.5"
{% else %}
- "2.7"
{%- endif %}
install:
- "pip install hitch"
- "cd tests"

View File

@ -1,14 +1,26 @@
FROM cookiecutterdjango/base
{% if cookiecutter.use_python2 == 'n' -%}
FROM python:3.5
{% else %}
FROM python:2.7
{%- endif %}
ENV PYTHONUNBUFFERED 1
# Requirements have to be pulled and installed here, otherwise caching won't work
ADD ./requirements /requirements
ADD ./requirements.txt /requirements.txt
COPY ./requirements /requirements
RUN pip install -r /requirements.txt
RUN pip install -r /requirements/local.txt
RUN pip install -r /requirements/production.txt
ADD . /app
RUN groupadd -r django && useradd -r -g django django
COPY . /app
RUN chown -R django /app
COPY ./compose/django/gunicorn.sh /gunicorn.sh
COPY ./compose/django/entrypoint.sh /entrypoint.sh
RUN sed -i 's/\r//' /entrypoint.sh
RUN sed -i 's/\r//' /gunicorn.sh
RUN chmod +x /entrypoint.sh && chown django /entrypoint.sh
RUN chmod +x /gunicorn.sh && chown django /gunicorn.sh
WORKDIR /app
ENTRYPOINT ["/app/compose/django/entrypoint.sh"]
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -0,0 +1,18 @@
{% if cookiecutter.use_python2 == 'n' -%}
FROM python:3.5
{% else %}
FROM python:2.7
{%- endif %}
ENV PYTHONUNBUFFERED 1
# Requirements have to be pulled and installed here, otherwise caching won't work
COPY ./requirements /requirements
RUN pip install -r /requirements/local.txt
COPY ./compose/django/entrypoint.sh /entrypoint.sh
RUN sed -i 's/\r//' /entrypoint.sh
RUN chmod +x /entrypoint.sh
WORKDIR /app
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -22,7 +22,6 @@ module.exports = function (grunt) {
images: this.app + '/static/images',
js: this.app + '/static/js',
manageScript: 'manage.py',
{% if cookiecutter.use_maildump=="y" -%}mailserverpid: 'mailserver.pid',{%- endif %}
}
};
@ -113,16 +112,16 @@ module.exports = function (grunt) {
runDjango: {
cmd: 'python <%= paths.manageScript %> runserver'
},
{% if cookiecutter.use_maildump == "y" -%}runMailDump: {
cmd: 'maildump -p <%= paths.mailserverpid %>'
},
stopMailDump: {
cmd: 'maildump -p <%= paths.mailserverpid %> --stop'
{% if cookiecutter.use_mailhog == "y" -%}runMailHog: {
cmd: './mailhog'
},{%- endif %}
}
});
grunt.registerTask('serve', [
{% if cookiecutter.use_mailhog == "y" -%}
'bgShell:runMailHog',
{%- endif %}
'bgShell:runDjango',
'watch'
]);
@ -135,12 +134,5 @@ module.exports = function (grunt) {
grunt.registerTask('default', [
'build'
]);
{% if cookiecutter.use_maildump == "y" -%}
grunt.registerTask('start-email-server', [
'bgShell:runMailDump'
]);
grunt.registerTask('stop-email-server', [
'bgShell:stopMailDump'
]);{%- endif %}
};

View File

@ -1,3 +1,13 @@
{% if cookiecutter.open_source_license == 'MIT' %}
The MIT License (MIT)
Copyright (c) {{ cookiecutter.year }}, {{ cookiecutter.author_name }}
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
{% elif cookiecutter.license == 'BSD' %}
Copyright (c) {{ cookiecutter.year }}, {{ cookiecutter.author_name }}
All rights reserved.
@ -25,3 +35,4 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
{% endif %}

View File

@ -1 +1,4 @@
web: gunicorn config.wsgi:application
{% if cookiecutter.use_celery == "y" -%}
worker: {% if cookiecutter.use_newrelic == "y" %}newrelic-admin run-program {% endif %}celery worker --app={{cookiecutter.repo_name}}.taskapp --loglevel=info
{%- endif %}

View File

@ -7,77 +7,14 @@
LICENSE: BSD
Settings
--------
------------
{{cookiecutter.project_name}} 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.
Moved to settings_.
For configuration purposes, the following table maps the '{{cookiecutter.project_name}}' environment variables to their Django setting:
.. _settings: http://cookiecutter-django.readthedocs.org/en/latest/settings.html
======================================= =========================== ============================================== ======================================================================
Environment Variable Django Setting Development Default Production Default
======================================= =========================== ============================================== ======================================================================
DJANGO_CACHES CACHES (default) locmem redis
DJANGO_DATABASES DATABASES (default) See code See code
DJANGO_DEBUG DEBUG True False
DJANGO_SECRET_KEY SECRET_KEY CHANGEME!!! raises error
DJANGO_SECURE_BROWSER_XSS_FILTER SECURE_BROWSER_XSS_FILTER n/a True
DJANGO_SECURE_SSL_REDIRECT SECURE_SSL_REDIRECT n/a True
DJANGO_SECURE_CONTENT_TYPE_NOSNIFF SECURE_CONTENT_TYPE_NOSNIFF n/a True
DJANGO_SECURE_FRAME_DENY SECURE_FRAME_DENY n/a True
DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS HSTS_INCLUDE_SUBDOMAINS n/a True
DJANGO_SESSION_COOKIE_HTTPONLY SESSION_COOKIE_HTTPONLY n/a True
DJANGO_SESSION_COOKIE_SECURE SESSION_COOKIE_SECURE n/a False
DJANGO_DEFAULT_FROM_EMAIL DEFAULT_FROM_EMAIL n/a "{{cookiecutter.project_name}} <noreply@{{cookiecutter.domain_name}}>"
DJANGO_SERVER_EMAIL SERVER_EMAIL n/a "{{cookiecutter.project_name}} <noreply@{{cookiecutter.domain_name}}>"
DJANGO_EMAIL_SUBJECT_PREFIX EMAIL_SUBJECT_PREFIX n/a "[{{cookiecutter.project_name}}] "
======================================= =========================== ============================================== ======================================================================
The following table lists settings and their defaults for third-party applications:
======================================= =========================== ============================================== ======================================================================
Environment Variable Django Setting Development Default Production Default
======================================= =========================== ============================================== ======================================================================
DJANGO_AWS_ACCESS_KEY_ID AWS_ACCESS_KEY_ID n/a raises error
DJANGO_AWS_SECRET_ACCESS_KEY AWS_SECRET_ACCESS_KEY n/a raises error
DJANGO_AWS_STORAGE_BUCKET_NAME AWS_STORAGE_BUCKET_NAME n/a raises error
{% if cookiecutter.use_sentry == "y" -%}DJANGO_SENTRY_DSN SENTRY_DSN n/a raises error
DJANGO_SENTRY_CLIENT SENTRY_CLIENT n/a raven.contrib.django.raven_compat.DjangoClient
DJANGO_SENTRY_LOG_LEVEL SENTRY_LOG_LEVEL n/a logging.INFO{%- endif %}
DJANGO_MAILGUN_API_KEY MAILGUN_ACCESS_KEY n/a raises error
DJANGO_MAILGUN_SERVER_NAME MAILGUN_SERVER_NAME n/a raises error
======================================= =========================== ============================================== ======================================================================
Getting up and running
----------------------
Basics
^^^^^^
The steps below will get you up and running with a local development environment. We assume you have the following installed:
* pip
* virtualenv
* PostgreSQL
First make sure to create and activate a virtualenv_, then open a terminal at the project root and install the requirements for local development::
$ pip install -r requirements/local.txt
.. _virtualenv: http://docs.python-guide.org/en/latest/dev/virtualenvs/
Create a local PostgreSQL database::
$ createdb {{ cookiecutter.repo_name }}
Run ``migrate`` on your new database::
$ python manage.py migrate
You can now run the ``runserver_plus`` command::
$ python manage.py runserver_plus
Open up your browser to http://127.0.0.1:8000/ to see the site running locally.
Basic Commands
--------------
Setting Up Your Users
^^^^^^^^^^^^^^^^^^^^^
@ -99,34 +36,25 @@ To run the tests, check your test coverage, and generate an HTML coverage report
$ coverage html
$ open htmlcov/index.html
Running tests with py.test
~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
$ py.test
Live reloading and Sass CSS compilation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you'd like to take advantage of live reloading and Sass / Compass CSS compilation you can do so with a little bit of prep work.
Moved to `Live reloading and SASS compilation`_.
Make sure that nodejs_ is installed. Then in the project root run::
$ npm install
.. _nodejs: http://nodejs.org/download/
If you don't already have it, install `compass` (doesn't hurt if you run this command twice)::
gem install compass
Now you just need::
$ grunt serve
The base app will now run as it would with the usual ``manage.py runserver`` but with live reloading and Sass compilation enabled.
To get live reloading to work you'll probably need to install an `appropriate browser extension`_
.. _appropriate browser extension: http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-
.. _`Live reloading and SASS compilation`: http://cookiecutter-django.readthedocs.org/en/latest/live-reloading-and-sass-compilation.html
{% if cookiecutter.use_celery == "y" %}
Celery
^^^^^^
This app comes with Celery.
To run a celery worker:
@ -136,31 +64,32 @@ To run a celery worker:
cd {{cookiecutter.repo_name}}
celery -A {{cookiecutter.repo_name}}.taskapp worker -l info
Please note: For Celerys import magic to work, it is important *where* the celery commands are run. If you are in the same folder with *manage.py*, you should be right.
Please note: For Celery's import magic to work, it is important *where* the celery commands are run. If you are in the same folder with *manage.py*, you should be right.
{% endif %}
{% if cookiecutter.use_maildump == "y" %}
{% if cookiecutter.use_mailhog == "y" %}
Email Server
^^^^^^^^^^^^
In development, it is often nice to be able to see emails that are being sent from your application. For this purpose,
a Grunt task exists to start an instance of `maildump`_ which is a local SMTP server with an online interface.
In development, it is often nice to be able to see emails that are being sent from your application. If you choose to use `MailHog`_ when generating the project a local SMTP server with a web interface will be available.
.. _maildump: https://github.com/ThiefMaster/maildump
.. _mailhog: https://github.com/mailhog/MailHog
Make sure you have nodejs installed, and then type the following::
To start the service, make sure you have nodejs installed, and then type the following::
$ grunt start-email-server
$ npm install
$ grunt serve
This will start an email server. The project is setup to deliver to the email server by default. To view messages
that are sent by your application, open your browser to http://127.0.0.1:1080
(After the first run you only need to type ``grunt serve``) This will start an email server that listens on ``127.0.0.1:1025`` in addition to starting your Django project and a watch task for live reload.
To stop the email server::
To view messages that are sent by your application, open your browser and go to ``http://127.0.0.1:8025``
$ grunt stop-email-server
The email server will exit when you exit the Grunt task on the CLI with Ctrl+C.
The email server listens on 127.0.0.1:1025
{% endif %}
{% if cookiecutter.use_sentry == "y" %}
Sentry
@ -170,6 +99,7 @@ Sentry is an error logging aggregator service. You can sign up for a free accoun
The system is setup with reasonable defaults, including 404 logging and integration with the WSGI application.
You must set the DSN url in production.
{% endif %}
It's time to write the code!!!
@ -202,195 +132,21 @@ The testing framework runs Django, Celery (if enabled), Postgres, HitchSMTP (a m
Deployment
----------
It is possible to deploy to Heroku, to your own server by using Dokku, an open source Heroku clone or using docker-compose.
We provide tools and instructions for deploying using Docker and Heroku.
Heroku
^^^^^^
Run these commands to deploy the project to Heroku:
.. image:: https://www.herokucdn.com/deploy/button.png
:target: https://heroku.com/deploy
.. code-block:: bash
See detailed `cookiecutter-django Heroku documentation`_.
heroku create --buildpack https://github.com/heroku/heroku-buildpack-python
heroku addons:create heroku-postgresql:hobby-dev
heroku pg:backups schedule --at '02:00 America/Los_Angeles' DATABASE_URL
heroku pg:promote DATABASE_URL
heroku addons:create heroku-redis:hobby-dev
heroku addons:create mailgun
heroku config:set DJANGO_SECRET_KEY=`openssl rand -base64 32`
heroku config:set DJANGO_SETTINGS_MODULE='config.settings.production'
heroku config:set DJANGO_AWS_ACCESS_KEY_ID=YOUR_AWS_ID_HERE
heroku config:set DJANGO_AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_ACCESS_KEY_HERE
heroku config:set DJANGO_AWS_STORAGE_BUCKET_NAME=YOUR_AWS_S3_BUCKET_NAME_HERE
heroku config:set DJANGO_MAILGUN_SERVER_NAME=YOUR_MALGUN_SERVER
heroku config:set DJANGO_MAILGUN_API_KEY=YOUR_MAILGUN_API_KEY
heroku config:set PYTHONHASHSEED=random
git push heroku master
heroku run python manage.py migrate
heroku run python manage.py check --deploy
heroku run python manage.py createsuperuser
heroku open
Dokku
^^^^^
You need to make sure you have a server running Dokku with at least 1GB of RAM. Backing services are
added just like in Heroku however you must ensure you have the relevant Dokku plugins installed.
.. code-block:: bash
cd /var/lib/dokku/plugins
git clone https://github.com/rlaneve/dokku-link.git link
git clone https://github.com/luxifer/dokku-redis-plugin redis
git clone https://github.com/jezdez/dokku-postgres-plugin postgres
dokku plugins-install
You can specify the buildpack you wish to use by creating a file name .env containing the following.
.. code-block:: bash
export BUILDPACK_URL=<repository>
You can then deploy by running the following commands.
.. code-block:: bash
git remote add dokku dokku@yourservername.com:{{cookiecutter.repo_name}}
git push dokku master
ssh -t dokku@yourservername.com dokku redis:create {{cookiecutter.repo_name}}-redis
ssh -t dokku@yourservername.com dokku redis:link {{cookiecutter.repo_name}}-redis {{cookiecutter.repo_name}}
ssh -t dokku@yourservername.com dokku postgres:create {{cookiecutter.repo_name}}-postgres
ssh -t dokku@yourservername.com dokku postgres:link {{cookiecutter.repo_name}}-postgres {{cookiecutter.repo_name}}
ssh -t dokku@yourservername.com dokku config:set {{cookiecutter.repo_name}} DJANGO_SECRET_KEY=RANDOM_SECRET_KEY_HERE
ssh -t dokku@yourservername.com dokku config:set {{cookiecutter.repo_name}} DJANGO_SETTINGS_MODULE='config.settings.production'
ssh -t dokku@yourservername.com dokku config:set {{cookiecutter.repo_name}} DJANGO_AWS_ACCESS_KEY_ID=YOUR_AWS_ID_HERE
ssh -t dokku@yourservername.com dokku config:set {{cookiecutter.repo_name}} DJANGO_AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_ACCESS_KEY_HERE
ssh -t dokku@yourservername.com dokku config:set {{cookiecutter.repo_name}} DJANGO_AWS_STORAGE_BUCKET_NAME=YOUR_AWS_S3_BUCKET_NAME_HERE
ssh -t dokku@yourservername.com dokku config:set {{cookiecutter.repo_name}} DJANGO_MAILGUN_API_KEY=YOUR_MAILGUN_API_KEY
ssh -t dokku@yourservername.com dokku config:set {{cookiecutter.repo_name}} DJANGO_MAILGUN_SERVER_NAME=YOUR_MAILGUN_SERVER
ssh -t dokku@yourservername.com dokku run {{cookiecutter.repo_name}} python manage.py migrate
ssh -t dokku@yourservername.com dokku run {{cookiecutter.repo_name}} python manage.py createsuperuser
When deploying via Dokku make sure you backup your database in some fashion as it is NOT done automatically.
.. _`cookiecutter-django Heroku documentation`: http://cookiecutter-django.readthedocs.org/en/latest/deployment-on-heroku.html
Docker
^^^^^^
**Warning**
See detailed `cookiecutter-django Docker documentation`_.
Docker is evolving extremely fast, but it has still some rough edges here and there. Compose is currently (as of version 1.4)
not considered production ready. That means you won't be able to scale to multiple servers and you won't be able to run
zero downtime deployments out of the box. Consider all this as experimental until you understand all the implications
to run docker (with compose) on production.
**Run your app with docker-compose**
Prerequisites:
* docker (tested with 1.8)
* docker-compose (tested with 0.4)
Before you start, check out the `docker-compose.yml` file in the root of this project. This is where each component
of this application gets its configuration from. It consists of a `postgres` service that runs the database, `redis`
for caching, `nginx` as reverse proxy and last but not least the `django` application run by gunicorn.
{% if cookiecutter.use_celery == 'y' %}
Since this application also runs Celery, there are two more services with a service called `celeryworker` that runs the
celery worker process and `celerybeat` that runs the celery beat process.
{% endif %}
All of these services except `redis` rely on environment variables set by you. There is an `env.example` file in the
root directory of this project as a starting point. Add your own variables to the file and rename it to `.env`. This
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.
By default, the application is configured to listen on all interfaces on port 80. If you want to change that, open the
`docker-compose.yml` file and replace `0.0.0.0` with your own ip. If you are using `nginx-proxy`_ to run multiple
application stacks on one host, remove the port setting entirely and add `VIRTUAL_HOST={{cookiecutter.domain_name}}` to your env file.
This pass all incoming requests on `nginx-proxy` to the nginx service your application is using.
.. _nginx-proxy: https://github.com/jwilder/nginx-proxy
Postgres is saving its database files to `/data/{{cookiecutter.repo_name}}/postgres` by default. Change that if you wan't
something else and make sure to make backups since this is not done automatically.
To get started, pull your code from source control (don't forget the `.env` file) and change to your projects root
directory.
You'll need to build the stack first. To do that, run::
docker-compose build
Once this is ready, you can run it with::
docker-compose up
To run a migration, open up a second terminal and run::
docker-compose run django python manage.py migrate
To create a superuser, run::
docker-compose run django python manage.py createsuperuser
If you need a shell, run::
docker-compose run django python manage.py shell_plus
Once you are ready with your initial setup, you wan't 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
it needs to do is to run `docker-compose up` in your projects root directory.
If you are using `supervisor`, you can use this file as a starting point::
[program:{{cookiecutter.repo_name}}]
command=docker-compose up
directory=/path/to/{{cookiecutter.repo_name}}
redirect_stderr=true
autostart=true
autorestart=true
priority=10
Place it in `/etc/supervisor/conf.d/{{cookiecutter.repo_name}}.conf` and run::
supervisorctl reread
supervisorctl start {{cookiecutter.repo_name}}
To get the status, run::
supervisorctl status
If you have errors, you can always check your stack with `docker-compose`. Switch to your projects root directory and run::
docker-compose ps
to get an output of all running containers.
To check your logs, run::
docker-compose logs
If you want to scale your application, run::
docker-compose scale django=4
docker-compose scale celeryworker=2
**Don't run the scale command on postgres or celerybeat**
.. _`cookiecutter-django Docker documentation`: http://cookiecutter-django.readthedocs.org/en/latest/deployment-with-docker.html

View File

@ -0,0 +1,38 @@
{
"name": "{{cookiecutter.repo_name}}",
"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": "",
{% if cookiecutter.use_newrelic == "y" -%}
"NEW_RELIC_LICENSE_KEY": "",
"NEW_RELIC_APP_NAME": "",
{%- endif %}
"DJANGO_MAILGUN_API_KEY": ""{% if cookiecutter.use_sentry == "y" -%},
"DJANGO_SENTRY_DSN": ""{%- endif %}
},
"scripts": {
"postdeploy": "python manage.py migrate"
},
"addons": [
"heroku-postgresql:hobby-dev",
"heroku-redis:hobby-dev",
"mailgun"
]
}

26
{{cookiecutter.repo_name}}/compose/django/entrypoint.sh Executable file → Normal file
View File

@ -4,29 +4,15 @@ set -e
# Since docker-compose relies heavily on environment variables itself for configuration, we'd have to define multiple
# environment variables just to support cookiecutter out of the box. That makes no sense, so this little entrypoint
# does all this for us.
export DJANGO_CACHE_URL=redis://redis:6379/0
export REDIS_URL=redis://redis:6379
# the official postgres image uses 'postgres' as default user if not set explictly.
if [ -z "$POSTGRES_ENV_POSTGRES_USER" ]; then
export POSTGRES_ENV_POSTGRES_USER=postgres
if [ -z "$POSTGRES_USER" ]; then
export POSTGRES_USER=postgres
fi
export DATABASE_URL=postgres://$POSTGRES_ENV_POSTGRES_USER:$POSTGRES_ENV_POSTGRES_PASSWORD@postgres:5432/$POSTGRES_ENV_POSTGRES_USER
export DATABASE_URL=postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres:5432/$POSTGRES_USER
{% if cookiecutter.use_celery == 'y' %}
export CELERY_BROKER_URL=$DJANGO_CACHE_URL
export CELERY_BROKER_URL=$REDIS_URL/0
{% endif %}
# create a user, with UID of host user,
# read more about that trick: http://stackoverflow.com/a/28596874/338581
TARGET_USER_GID=$(stat -c "%u" /app)
useradd -m -s /bin/bash -u $TARGET_USER_GID django
echo -e "\n------------------------------------------------------------\n"
su -c "npm install" django
echo -e "\n------------------------------------------------------------\n"
su -c "grunt build" django
echo -e "\n------------------------------------------------------------\n"
# somehow, when $@ is used directly, this doesn't work
COMMAND=$@
su -c "$COMMAND" django
exec "$@"

View File

@ -0,0 +1,11 @@
FROM postgres:9.5
# add backup scripts
ADD backup.sh /usr/local/bin/backup
ADD restore.sh /usr/local/bin/restore
ADD list-backups.sh /usr/local/bin/list-backups
# make them executable
RUN chmod +x /usr/local/bin/restore
RUN chmod +x /usr/local/bin/list-backups
RUN chmod +x /usr/local/bin/backup

View File

@ -0,0 +1,22 @@
#!/bin/bash
# stop on errors
set -e
# we might run into trouble when using the default `postgres` user, e.g. when dropping the postgres
# database in restore.sh. Check that something else is used here
if [ "$POSTGRES_USER" == "postgres" ]
then
echo "creating a backup as the postgres user is not supported, make sure to set the POSTGRES_USER environment variable"
exit 1
fi
# export the postgres password so that subsequent commands don't ask for it
export PGPASSWORD=$POSTGRES_PASSWORD
echo "creating backup"
echo "---------------"
FILENAME=backup_$(date +'%Y_%m_%dT%H_%M_%S').sql
pg_dump -h postgres -U $POSTGRES_USER >> /backups/$FILENAME
echo "successfully created backup $FILENAME"

View File

@ -0,0 +1,4 @@
#!/bin/bash
echo "listing available backups"
echo "-------------------------"
ls /backups/

View File

@ -0,0 +1,56 @@
#!/bin/bash
# stop on errors
set -e
# we might run into trouble when using the default `postgres` user, e.g. when dropping the postgres
# database in restore.sh. Check that something else is used here
if [ "$POSTGRES_USER" == "postgres" ]
then
echo "restoring as the postgres user is not supported, make sure to set the POSTGRES_USER environment variable"
exit 1
fi
# export the postgres password so that subsequent commands don't ask for it
export PGPASSWORD=$POSTGRES_PASSWORD
# check that we have an argument for a filename candidate
if [[ $# -eq 0 ]] ; then
echo 'usage:'
echo ' docker-compose run postgres restore <backup-file>'
echo ''
echo 'to get a list of available backups, run:'
echo ' docker-compose run postgres list-backups'
exit 1
fi
# set the backupfile variable
BACKUPFILE=/backups/$1
# check that the file exists
if ! [ -f $BACKUPFILE ]; then
echo "backup file not found"
echo 'to get a list of available backups, run:'
echo ' docker-compose run postgres list-backups'
exit 1
fi
echo "beginning restore from $1"
echo "-------------------------"
# delete the db
# deleting the db can fail. Spit out a comment if this happens but continue since the db
# is created in the next step
echo "deleting old database $POSTGRES_USER"
if dropdb -h postgres -U $POSTGRES_USER $POSTGRES_USER
then echo "deleted $POSTGRES_USER database"
else echo "database $POSTGRES_USER does not exist, continue"
fi
# create a new database
echo "creating new database $POSTGRES_USER"
createdb -h postgres -U $POSTGRES_USER $POSTGRES_USER -O $POSTGRES_USER
# restore the database
echo "restoring database $POSTGRES_USER"
psql -h postgres -U $POSTGRES_USER < $BACKUPFILE

View File

@ -212,6 +212,10 @@ ACCOUNT_AUTHENTICATION_METHOD = 'username'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True)
ACCOUNT_ADAPTER = '{{cookiecutter.repo_name}}.users.adapters.AccountAdapter'
SOCIALACCOUNT_ADAPTER = '{{cookiecutter.repo_name}}.users.adapters.SocialAccountAdapter'
# Custom user app defaults
# Select the correct user model
AUTH_USER_MODEL = 'users.User'
@ -220,39 +224,6 @@ LOGIN_URL = 'account_login'
# SLUGLIFIER
AUTOSLUG_SLUGIFY_FUNCTION = 'slugify.slugify'
# LOGGING CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#logging
# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
}
}
{% if cookiecutter.use_celery == "y" %}
########## CELERY
INSTALLED_APPS += ('{{cookiecutter.repo_name}}.taskapp.celery.CeleryConfig',)
@ -261,4 +232,8 @@ INSTALLED_APPS += ('kombu.transport.django',)
BROKER_URL = env("CELERY_BROKER_URL", default='django://')
########## END CELERY
{% endif %}
# Location of root django.contrib.admin URL, use {% raw %}{% url 'admin:index' %}{% endraw %}
ADMIN_URL = r'^admin/'
# Your common stuff: Below this line define 3rd party library settings

View File

@ -25,7 +25,7 @@ SECRET_KEY = env("DJANGO_SECRET_KEY", default='CHANGEME!!!')
# ------------------------------------------------------------------------------
EMAIL_HOST = 'localhost'
EMAIL_PORT = 1025
{%if cookiecutter.use_maildump == "n" -%}
{%if cookiecutter.use_mailhog == "n" -%}
EMAIL_BACKEND = env('DJANGO_EMAIL_BACKEND',
default='django.core.mail.backends.console.EmailBackend')
{%- endif %}
@ -60,7 +60,7 @@ INSTALLED_APPS += ('django_extensions', )
# TESTING
# ------------------------------------------------------------------------------
TEST_RUNNER = 'django.test.runner.DiscoverRunner'
{% if cookiecutter.celery_support == "y" %}
{% if cookiecutter.use_celery == "y" %}
########## CELERY
# In development, all tasks will be executed locally by blocking until the task returns
CELERY_ALWAYS_EAGER = True

View File

@ -9,6 +9,9 @@ Production Configurations
{% if cookiecutter.use_sentry == "y" %}
- Use sentry for error logging
{% endif %}
{% if cookiecutter.use_opbeat == "y" %}
- Use opbeat for error reporting
{% endif %}
'''
from __future__ import absolute_import, unicode_literals
@ -52,7 +55,19 @@ MIDDLEWARE_CLASSES = SECURITY_MIDDLEWARE + \
MIDDLEWARE_CLASSES = SECURITY_MIDDLEWARE + MIDDLEWARE_CLASSES
{%- endif %}
{% if cookiecutter.use_opbeat == "y" -%}
# opbeat integration
# See https://opbeat.com/languages/django/
INSTALLED_APPS += ('opbeat.contrib.django',)
OPBEAT = {
'ORGANIZATION_ID': env('DJANGO_OPBEAT_ORGANIZATION_ID'),
'APP_ID': env('DJANGO_OPBEAT_APP_ID'),
'SECRET_TOKEN': env('DJANGO_OPBEAT_SECRET_TOKEN')
}
MIDDLEWARE_CLASSES = (
'opbeat.contrib.django.middleware.OpbeatAPMMiddleware',
) + MIDDLEWARE_CLASSES
{%- endif %}
# set this to 60 seconds and then to 518400 when you can prove it works
SECURE_HSTS_SECONDS = 60
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool(
@ -69,7 +84,7 @@ SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True)
# ------------------------------------------------------------------------------
# Hosts/domain names that are valid for this site
# See https://docs.djangoproject.com/en/1.6/ref/settings/#allowed-hosts
ALLOWED_HOSTS = ["*"]
ALLOWED_HOSTS = env.list('DJANGO_ALLOWED_HOSTS', default=['{{cookiecutter.domain_name}}'])
# END SITE CONFIGURATION
INSTALLED_APPS += ("gunicorn", )
@ -82,7 +97,6 @@ INSTALLED_APPS += ("gunicorn", )
INSTALLED_APPS += (
'storages',
)
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
AWS_ACCESS_KEY_ID = env('DJANGO_AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = env('DJANGO_AWS_SECRET_ACCESS_KEY')
@ -104,15 +118,25 @@ AWS_HEADERS = {
# URL that handles the media served from MEDIA_ROOT, used for managing
# stored files.
{% if cookiecutter.use_whitenoise == 'y' -%}
MEDIA_URL = 'https://s3.amazonaws.com/%s/' % AWS_STORAGE_BUCKET_NAME
{% else %}
# See:http://stackoverflow.com/questions/10390244/
from storages.backends.s3boto import S3BotoStorage
StaticRootS3BotoStorage = lambda: S3BotoStorage(location='static')
MediaRootS3BotoStorage = lambda: S3BotoStorage(location='media')
DEFAULT_FILE_STORAGE = 'config.settings.production.MediaRootS3BotoStorage'
# Static Assests
MEDIA_URL = 'https://s3.amazonaws.com/%s/media/' % AWS_STORAGE_BUCKET_NAME
{%- endif %}
# Static Assets
# ------------------------
{% if cookiecutter.use_whitenoise == 'y' -%}
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
{% else %}
STATICFILES_STORAGE = DEFAULT_FILE_STORAGE
STATIC_URL = MEDIA_URL
STATIC_URL = 'https://s3.amazonaws.com/%s/static/' % AWS_STORAGE_BUCKET_NAME
STATICFILES_STORAGE = 'config.settings.production.StaticRootS3BotoStorage'
# See: https://github.com/antonagestam/collectfast
# For Django 1.7+, 'collectfast' should come before
@ -130,6 +154,10 @@ MAILGUN_ACCESS_KEY = env('DJANGO_MAILGUN_API_KEY')
MAILGUN_SERVER_NAME = env('DJANGO_MAILGUN_SERVER_NAME')
EMAIL_SUBJECT_PREFIX = env("DJANGO_EMAIL_SUBJECT_PREFIX", default='[{{cookiecutter.project_name}}] ')
SERVER_EMAIL = env('DJANGO_SERVER_EMAIL', default=DEFAULT_FROM_EMAIL)
{% if cookiecutter.use_newrelic == 'y'-%}
NEW_RELIC_LICENSE_KEY = env('NEW_RELIC_LICENSE_KEY')
NEW_RELIC_APP_NAME = env('NEW_RELIC_APP_NAME')
{%- endif %}
# TEMPLATE CONFIGURATION
# ------------------------------------------------------------------------------
@ -151,7 +179,7 @@ DATABASES['default'] = env.db("DATABASE_URL")
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "{0}/{1}".format(env.cache_url('REDIS_URL', default="redis://127.0.0.1:6379"), 0),
"LOCATION": "{0}/{1}".format(env('REDIS_URL', default="redis://127.0.0.1:6379"), 0),
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"IGNORE_EXCEPTIONS": True, # mimics memcache behavior.
@ -162,7 +190,8 @@ CACHES = {
{% if cookiecutter.use_sentry == "y" %}
# Sentry Configuration
SENTRY_CLIENT = env('DJANGO_SENTRY_CLIENT')
SENTRY_DSN = env('DJANGO_SENTRY_DSN')
SENTRY_CLIENT = env('DJANGO_SENTRY_CLIENT', default='raven.contrib.django.raven_compat.DjangoClient')
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
@ -203,11 +232,68 @@ LOGGING = {
'handlers': ['console'],
'propagate': False,
},
'django.security.DisallowedHost': {
'level': 'ERROR',
'handlers': ['console', 'sentry'],
'propagate': False,
},
},
}
SENTRY_CELERY_LOGLEVEL = env('DJANGO_SENTRY_LOG_LEVEL', logging.INFO)
SENTRY_CELERY_LOGLEVEL = env.int('DJANGO_SENTRY_LOG_LEVEL', logging.INFO)
RAVEN_CONFIG = {
'CELERY_LOGLEVEL': env('DJANGO_SENTRY_LOG_LEVEL', logging.INFO)
'CELERY_LOGLEVEL': env.int('DJANGO_SENTRY_LOG_LEVEL', logging.INFO),
'DSN': SENTRY_DSN
}
{% elif cookiecutter.use_sentry == "n" %}
# LOGGING CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#logging
# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'formatters': {
'verbose': {
'format': '%(levelname)s %(asctime)s %(module)s '
'%(process)d %(thread)d %(message)s'
},
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True
},
'django.security.DisallowedHost': {
'level': 'ERROR',
'handlers': ['console', 'mail_admins'],
'propagate': True
}
}
}
{% endif %}
# Custom Admin URL, use {% raw %}{% url 'admin:index' %}{% endraw %}
ADMIN_URL = env('DJANGO_ADMIN_URL')
# Your production stuff: Below this line define 3rd party library settings

View File

@ -6,13 +6,14 @@ from django.conf.urls import include, url
from django.conf.urls.static import static
from django.contrib import admin
from django.views.generic import TemplateView
from django.views import defaults as default_views
urlpatterns = [
url(r'^$', TemplateView.as_view(template_name='pages/home.html'), name="home"),
url(r'^about/$', TemplateView.as_view(template_name='pages/about.html'), name="about"),
# Django Admin
url(r'^admin/', include(admin.site.urls)),
# Django Admin, use {% raw %}{% url 'admin:index' %}{% endraw %}
url(settings.ADMIN_URL, include(admin.site.urls)),
# User management
url(r'^users/', include("{{ cookiecutter.repo_name }}.users.urls", namespace="users")),
@ -27,8 +28,8 @@ if settings.DEBUG:
# This allows the error pages to be debugged during development, just visit
# these url in browser to see how these error pages look like.
urlpatterns += [
url(r'^400/$', 'django.views.defaults.bad_request'),
url(r'^403/$', 'django.views.defaults.permission_denied'),
url(r'^404/$', 'django.views.defaults.page_not_found'),
url(r'^500/$', 'django.views.defaults.server_error'),
url(r'^400/$', default_views.bad_request, kwargs={'exception': Exception("Bad Request!")}),
url(r'^403/$', default_views.permission_denied, kwargs={'exception': Exception("Permission Denied")}),
url(r'^404/$', default_views.page_not_found, kwargs={'exception': Exception("Page not Found")}),
url(r'^500/$', default_views.server_error),
]

View File

@ -15,12 +15,18 @@ framework.
"""
import os
{% if cookiecutter.use_newrelic == "y" -%}
if os.environ.get("DJANGO_SETTINGS_MODULE") == "config.settings.production":
import newrelic.agent
newrelic.agent.initialize()
{%- endif %}
from django.core.wsgi import get_wsgi_application
{% if cookiecutter.use_whitenoise == 'y' -%}
from whitenoise.django import DjangoWhiteNoise
{%- endif %}
{% if cookiecutter.use_sentry == "y" -%}
from raven.contrib.django.raven_compat.middleware.wsgi import Sentry
if os.environ.get("DJANGO_SETTINGS_MODULE") == "config.settings.production":
from raven.contrib.django.raven_compat.middleware.wsgi import Sentry
{%- endif %}
# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks
@ -40,9 +46,13 @@ application = get_wsgi_application()
application = DjangoWhiteNoise(application)
{%- endif %}
{% if cookiecutter.use_sentry == "y" -%}
application = Sentry(application)
if os.environ.get("DJANGO_SETTINGS_MODULE") == "config.settings.production":
application = Sentry(application)
{%- endif %}
{% if cookiecutter.use_newrelic == "y" -%}
if os.environ.get("DJANGO_SETTINGS_MODULE") == "config.settings.production":
application = newrelic.agent.WSGIApplicationWrapper(application)
{%- endif %}
# Apply WSGI middleware here.
# from helloworld.wsgi import HelloWorldApplication
# application = HelloWorldApplication(application)

View File

@ -1,13 +1,24 @@
postgres:
image: postgres
version: '2'
services:
postgres:
build: ./compose/postgres
volumes:
# If you are using boot2docker, postgres data has to live in the VM for now until #581 is fixed
# for more info see here: https://github.com/boot2docker/boot2docker/issues/581
- /data/{{cookiecutter.repo_name}}/postgres:/var/lib/postgresql/data
- /data/dev/{{cookiecutter.repo_name}}/postgres:/var/lib/postgresql/data
- /data/dev/{{cookiecutter.repo_name}}/postgres-backups:/backups
environment:
- POSTGRES_USER={{cookiecutter.repo_name}}
django:
build: .
django:
build:
context: .
dockerfile: Dockerfile-dev
command: python /app/manage.py runserver_plus 0.0.0.0:8000
depends_on:
- postgres
environment:
- POSTGRES_USER={{cookiecutter.repo_name}}
volumes:
- .:/app
ports:

View File

@ -1,45 +1,58 @@
postgres:
image: postgres:9.4
version: '2'
services:
postgres:
build: ./compose/postgres
volumes:
- /data/{{cookiecutter.repo_name}}/postgres:/var/lib/postgresql/data
- /data/{{cookiecutter.repo_name}}/postgres-backups:/backups
env_file: .env
django:
build: .
django:
build:
context: .
user: django
links:
depends_on:
- postgres
- redis
command: /app/compose/django/gunicorn.sh
command: /gunicorn.sh
env_file: .env
depends_on:
- postgres
- redis
nginx:
nginx:
build: ./compose/nginx
links:
depends_on:
- django
ports:
- "0.0.0.0:80:80"
redis:
redis:
image: redis:3.0
{% if cookiecutter.use_celery == 'y' %}
celeryworker:
build: .
{% if cookiecutter.use_celery == 'y' %}
celeryworker:
build:
context: .
user: django
env_file: .env
links:
depends_on:
- postgres
- redis
command: celery -A {{cookiecutter.repo_name}}.taskapp worker -l INFO
depends_on:
- postgres
- redis
celerybeat:
build: .
celerybeat:
build:
context: .
user: django
env_file: .env
links:
depends_on:
- postgres
- redis
command: celery -A {{cookiecutter.repo_name}}.taskapp beat -l INFO
{% endif %}
depends_on:
- postgres
- redis
{% endif %}

View File

@ -1,8 +1,10 @@
POSTGRES_PASSWORD=mysecretpass
POSTGRES_USER=postgresuser
DJANGO_ADMIN_URL=
DJANGO_SETTINGS_MODULE=config.settings.production
DJANGO_SECRET_KEY=
DJANGO_SECRET_KEY=CHANGEME!!!
DJANGO_ALLOWED_HOSTS=.{{ cookiecutter.domain_name }}
DJANGO_AWS_ACCESS_KEY_ID=
DJANGO_AWS_SECRET_ACCESS_KEY=
DJANGO_AWS_STORAGE_BUCKET_NAME=
@ -10,3 +12,16 @@ DJANGO_MAILGUN_API_KEY=
DJANGO_MAILGUN_SERVER_NAME=
DJANGO_SERVER_EMAIL=
DJANGO_SECURE_SSL_REDIRECT=False
DJANGO_ACCOUNT_ALLOW_REGISTRATION=True
{% if cookiecutter.use_sentry == 'y' -%}
DJANGO_SENTRY_DSN=
{% endif %}
{% if cookiecutter.use_newrelic == 'y' -%}
NEW_RELIC_LICENSE_KEY=
NEW_RELIC_APP_NAME={{cookiecutter.repo_name}}
{% endif %}
{% if cookiecutter.use_opbeat == 'y' -%}
DJANGO_OPBEAT_ORGANIZATION_ID
DJANGO_OPBEAT_APP_ID
DJANGO_OPBEAT_SECRET_TOKEN
{% endif %}

View File

@ -24,7 +24,7 @@ function usage_message()
# Read the requirements.apt file, and remove comments and blank lines
function list_packages(){
cat ${OS_REQUIREMENTS_FILENAME} | grep -v "#" | grep -v "^$";
grep -v "#" ${OS_REQUIREMENTS_FILENAME} | grep -v "^$";
}
function install()

View File

@ -3,7 +3,7 @@
pip --version >/dev/null 2>&1 || {
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 "wget https://bootstrap.pypa.io/get-pip.py; chmod +x get-pip.py; sudo ./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"
echo >&2 -e "\n"
echo >&2 -e "\nFor more information, see pip documentation: https://pip.pypa.io/en/latest/"
exit 1;
@ -12,7 +12,7 @@ pip --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 "You can install it by running the following command:\n"
echo >&2 "sudo pip install virtualenv"
echo >&2 "sudo -H pip3 install virtualenv"
echo >&2 -e "\n"
echo >&2 -e "\nFor more information, see virtualenv documentation: https://virtualenv.pypa.io/en/latest/"
exit 1;
@ -21,7 +21,7 @@ virtualenv --version >/dev/null 2>&1 || {
if [ -z "$VIRTUAL_ENV" ]; then
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 "virtualenv venv"
echo >&2 -e "virtualenv venv --python=\`which python3\`"
echo >&2 -e "\nTo leave/disable the currently active virtualenv, run the following command:\n"
echo >&2 "deactivate"
echo >&2 -e "\nTo activate the virtualenv again, run the following command:\n"

View File

@ -0,0 +1,2 @@
[pytest]
DJANGO_SETTINGS_MODULE=config.settings.local

View File

@ -1,45 +1,58 @@
{% if cookiecutter.use_python2 == 'n' -%}
# Wheel 0.25+ needed to install certain packages on CPython 3.5+
# like Pillow and psycopg2
# See http://bitly.com/wheel-building-fails-CPython-35
# Verified bug on Python 3.5.1
wheel==0.29.0
{%- endif %}
# Bleeding edge Django
django==1.8.4
django==1.9.4
# Configuration
django-environ==0.3.0
django-environ==0.4.0
django-secure==1.0.1
{% if cookiecutter.use_whitenoise == 'y' -%}
whitenoise==2.0.3
whitenoise==2.0.6
{%- endif %}
# Forms
django-braces==1.8.1
django-crispy-forms==1.5.0
django-floppyforms==1.5.2
django-crispy-forms==1.6.0
django-floppyforms==1.6.1
# Models
django-model-utils==2.3.1
django-model-utils==2.4
# Images
Pillow==2.9.0
Pillow==3.1.1
# For user registration, either via email or social
# Well-built with regular release cycles!
django-allauth==0.23.0
django-allauth==0.24.1
# For the persistence stores
{% if cookiecutter.windows == 'y' -%}
# On Windows, you must download/install psycopg2 manually
# from http://www.lfd.uci.edu/~gohlke/pythonlibs/#psycopg
{% else %}
# Python-PostgreSQL Database Adapter
psycopg2==2.6.1
{%- endif %}
# Unicode slugification
unicode-slugify==0.1.3
django-autoslug==1.8.0
django-autoslug==1.9.3
# Time zones support
pytz==2015.4
pytz==2015.7
# Redis support
django-redis==4.2.0
django-redis==4.3.0
redis>=2.10.0
{% if cookiecutter.use_celery == "y" %}
celery==3.1.18
celery==3.1.21
{% endif %}
# Your custom requirements go here

View File

@ -1,21 +1,19 @@
# Local development dependencies go here
-r base.txt
coverage==3.7.1
coverage==4.0.3
django_coverage_plugin==1.2.2
Sphinx
django-extensions==1.5.5
Werkzeug==0.10.4
django-test-plus==1.0.8
factory_boy==2.5.2
django-extensions==1.6.1
Werkzeug==0.11.4
django-test-plus==1.0.12
factory_boy==2.6.1
# django-debug-toolbar that works with Django 1.5+
django-debug-toolbar==1.3.2
django-debug-toolbar==1.4
# improved REPL
ipdb==0.8.1
ipdb==0.9.0
{% if cookiecutter.use_maildump == "y" -%}
# Required by maildump. Need to pin dependency to gevent beta to be Python 3-compatible.
gevent==1.1b2
# Enables better email testing
maildump==0.5.1
{%- endif %}
# pytest!
pytest-django==2.9.1
pytest-sugar==0.5.1

View File

@ -2,25 +2,49 @@
# production that isn't in development.
-r base.txt
{% if cookiecutter.windows == 'y' -%}
# Python-PostgreSQL Database Adapter
# If using Win for dev, this assumes Unix in prod
# ------------------------------------------------
psycopg2==2.6.1
{%- endif %}
# WSGI Handler
# ------------------------------------------------
{% if cookiecutter.use_python2 == 'y' -%}
gevent==1.0.2
gunicorn==19.3.0
{% else %}
# there's no python 3 support in stable, have to use the latest release candidate for gevent
gevent==1.1rc5
{% endif %}
gunicorn==19.4.5
# Static and Media Storage
# ------------------------------------------------
boto==2.38.0
django-storages-redux==1.3
boto==2.39.0
django-storages-redux==1.3.2
{% if cookiecutter.use_whitenoise != 'y' -%}
Collectfast==0.2.3
{%- endif %}
# Mailgun Support
# ---------------
django-mailgun==0.2.2
django-mailgun==0.8.0
{% if cookiecutter.use_sentry == "y" -%}
# Raven is the Sentry client
# --------------------------
raven
{%- endif %}
{% if cookiecutter.use_newrelic == "y" -%}
# Newrelic agent for performance monitoring
# -----------------------------------------
newrelic
{%- endif %}
{% if cookiecutter.use_opbeat == "y" -%}
# Opbeat agent for performance monitoring
# -----------------------------------------
opbeat
{%- endif %}

View File

@ -1,6 +1,18 @@
# Test dependencies go here.
-r base.txt
coverage==4.0b1
flake8==2.4.1
django-test-plus==1.0.8
factory_boy==2.5.2
{% if cookiecutter.windows == 'y' -%}
# Python-PostgreSQL Database Adapter
# If using Win for dev, this assumes Unix in test/prod
psycopg2==2.6.1
{%- endif %}
coverage==4.0.3
django_coverage_plugin==1.2.2
flake8==2.5.4
django-test-plus==1.0.12
factory_boy==2.6.1
# pytest!
pytest-django==2.9.1
pytest-sugar==0.5.1

View File

@ -0,0 +1,5 @@
{% if cookiecutter.use_python2 == 'n' -%}
python-3.5.1
{% else %}
python-2.7.10
{%- endif %}

View File

@ -1,4 +1,7 @@
[flake8]
#ignore = E265
max-line-length = 120
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs
exclude = .tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules
[pep8]
max-line-length = 120
exclude=.tox,.git,*/migrations/*,*/static/CACHE/*,docs,node_modules

View File

@ -0,0 +1,21 @@
# Global settings for your hitch tests
failfast: true
xvfb: false
pause_on_success: false
pause_on_failure: false
startup_timeout: 45
shutdown_timeout: 5
environment_variables:
DATABASE_URL: postgres://{{cookiecutter.repo_name}}:password@127.0.0.1:15432/{{cookiecutter.repo_name}}
SECRET_KEY: cj5^uos4tfCdfghjkf5hq$9$(@-79^e9&x$3vyf#igvsfm4d=+
CELERY_BROKER_URL: redis://localhost:16379
DJANGO_EMAIL_BACKEND: django.core.mail.backends.smtp.EmailBackend
window_size:
width: 1024
height: 600
python_version: {% if cookiecutter.use_python2 == 'n' %}3.5.0{% else %}2.7.10{% endif %}
environment:
- approved_platforms:
- linux
- darwin

View File

@ -0,0 +1,15 @@
# Continuous integration settings for your tests
#
# Run with : hitch test . --settings ci.settings
#
# * Does not stop test run on first failure.
# * Firefox is run headless.
# * Start up timeout is higher (CI machines are not always powerful)
failfast: false
xvfb: true
startup_timeout: 60
# Comment out in Jenkins or other CI environments that don't print
# color characters correctly:
# colorless: true

View File

@ -19,30 +19,25 @@ class ExecutionEngine(hitchtest.ExecutionEngine):
def set_up(self):
"""Ensure virtualenv present, then run all services."""
python_package = hitchpython.PythonPackage(
python_version=self.preconditions['python_version']
python_version=self.settings['python_version']
)
python_package.build()
python_package.verify()
call([
python_package.pip, "install", "-r",
path.join(PROJECT_DIRECTORY, "requirements/local.txt")
])
postgres_package = hitchpostgres.PostgresPackage(
version=self.settings["postgres_version"],
)
postgres_package = hitchpostgres.PostgresPackage()
postgres_package.build()
postgres_package.verify()
redis_package = hitchredis.RedisPackage(version="2.8.4")
redis_package = hitchredis.RedisPackage()
redis_package.build()
redis_package.verify()
self.services = hitchserve.ServiceBundle(
project_directory=PROJECT_DIRECTORY,
startup_timeout=float(self.settings["startup_timeout"]),
shutdown_timeout=5.0,
shutdown_timeout=float(self.settings["shutdown_timeout"]),
)
postgres_user = hitchpostgres.PostgresUser("{{cookiecutter.repo_name}}", "password")
@ -58,7 +53,6 @@ class ExecutionEngine(hitchtest.ExecutionEngine):
self.services['Django'] = hitchpython.DjangoService(
python=python_package.python,
port=8000,
version=str(self.settings.get("django_version")),
settings="config.settings.local",
needs=[self.services['Postgres'], ],
env_vars=self.settings['environment_variables'],
@ -68,10 +62,9 @@ class ExecutionEngine(hitchtest.ExecutionEngine):
redis_package=redis_package,
port=16379,
)
{% if cookiecutter.celery_support == "y" %}
{% if cookiecutter.use_celery == "y" %}
self.services['Celery'] = hitchpython.CeleryService(
python=python_package.python,
version="3.1.18",
app="{{cookiecutter.repo_name}}.taskapp", loglevel="INFO",
needs=[
self.services['Redis'], self.services['Django'],
@ -80,7 +73,7 @@ class ExecutionEngine(hitchtest.ExecutionEngine):
)
{% endif %}
self.services['Firefox'] = hitchselenium.SeleniumService(
xvfb=self.settings.get("quiet", False),
xvfb=self.settings.get("xvfb", False),
no_libfaketime=True,
)
@ -93,9 +86,23 @@ class ExecutionEngine(hitchtest.ExecutionEngine):
self.services.startup(interactive=False)
# Configure selenium driver
# Docs : https://hitchtest.readthedocs.org/en/latest/plugins/hitchselenium.html
self.driver = self.services['Firefox'].driver
self.driver.set_window_size(self.settings['window_size']['height'], self.settings['window_size']['width'])
self.webapp = hitchselenium.SeleniumStepLibrary(
selenium_webdriver=self.driver,
wait_for_timeout=5,
)
# Add selenium steps
self.click = self.webapp.click
self.wait_to_appear = self.webapp.wait_to_appear
self.wait_to_contain = self.webapp.wait_to_contain
self.wait_for_any_to_contain = self.webapp.wait_for_any_to_contain
self.click_and_dont_wait_for_page_load = self.webapp.click_and_dont_wait_for_page_load
# Configure selenium driver
self.driver.set_window_size(self.settings['window_size']['width'], self.settings['window_size']['height'])
self.driver.set_window_position(0, 0)
self.driver.implicitly_wait(2.0)
self.driver.accept_next_alert = True
@ -111,24 +118,23 @@ class ExecutionEngine(hitchtest.ExecutionEngine):
def load_website(self):
"""Navigate to website in Firefox."""
self.driver.get(self.services['Django'].url())
def click(self, on):
"""Click on HTML id."""
self.driver.find_element_by_id(on).click()
self.click("djHideToolBarButton")
def fill_form(self, **kwargs):
"""Fill in a form with id=value."""
for element, text in kwargs.items():
self.driver.find_element_by_id(element).send_keys(text)
def click_submit(self):
"""Click on a submit button if it exists."""
self.driver.find_element_by_css_selector("button[type=\"submit\"]").click()
def confirm_emails_sent(self, number):
"""Count number of emails sent by app."""
assert len(self.services['HitchSMTP'].logs.json()) == int(number)
def click_on_link_in_last_email(self, which=1):
"""Click on the nth link in the last email sent."""
self.driver.get(
self.services['HitchSMTP'].logs.json()[-1]['links'][which - 1]
)
def wait_for_email(self, containing=None):
"""Wait for, and return email."""
self.services['HitchSMTP'].logs.out.tail.until_json(

View File

@ -1,26 +1,43 @@
click==5.1
colorama==0.3.3
backports-abc==0.4
click==6.3
colorama==0.3.6
decorator==4.0.9
docopt==0.6.2
faketime==0.9.6.3
hitchcron==0.2
hitchpostgres==0.6.2
hitchpython==0.3.2
hitchredis==0.4.1
hitchselenium==0.4
hitchserve==0.4.3
hitchpostgres==0.7.0
hitchpython==0.5.3
hitchredis==0.4.6
hitchselenium==0.5.1
hitchserve==0.4.9
hitchsmtp==0.2.1
hitchtest==0.7.5
hitchsystem==0.1.3
hitchtest==0.9.8
humanize==0.5.1
ipython==4.0.0
ipython==4.1.2
ipython-genutils==0.1.0
Jinja2==2.8
jupyter-client==4.2.0
jupyter-core==4.0.6
MarkupSafe==0.23
patool==1.8
psutil==3.1.1
python-build==0.2.1
pyuv==1.1.0
path.py==8.1.2
patool==1.12
pexpect==4.0.1
pickleshare==0.6
psutil==4.0.0
ptyprocess==0.5.1
pykwalify==1.5.0
python-build==0.2.13
python-dateutil==2.5.0
pyuv==1.2.0
PyYAML==3.11
requests==2.7.0
selenium==2.47.1
six==1.9.0
tblib==1.1.0
tornado==4.2.1
pyzmq==15.2.0
requests==2.9.1
selenium==2.52.0
simplegeneric==0.8.1
six==1.10.0
tblib==1.2.0
tornado==4.3
traitlets==4.1.0
unixpackage==0.4.1
xeger==0.3

View File

@ -0,0 +1,18 @@
- name: Sign up and log in
scenario:
- Load website
- Click: sign-up-link
- Fill form:
id_username: testuser
id_email: testuser@domain.com
id_password1: password
id_password2: password
- Click: sign-up-button
- Wait for email:
containing: Please Confirm Your E-mail Address
- Click on link in last email
- Click: confirm-button
- Fill form:
id_login: testuser
id_password: password
- Click: sign-in-button

View File

@ -1,59 +0,0 @@
postgres_version: 9.3.9
redis_version: 2.8.4
django_version: 1.8.3
celery_version: 3.1.18
pause_on_success: false
pause_on_failure: true
startup_timeout: 45
environment_variables:
DATABASE_URL: postgres://{{cookiecutter.repo_name}}:password@127.0.0.1:15432/{{cookiecutter.repo_name}}
SECRET_KEY: cj5^uos4tfCdfghjkf5hq$9$(@-79^e9&x$3vyf#igvsfm4d=+
CELERY_BROKER_URL: redis://localhost:16379
window_size:
width: 450
height: 450
python_versions:
- 2.7.10
environment:
- approved_platforms:
- linux
- darwin
- freeports:
- 1025
- 8000
- 15432
- 16379
- brew:
- libtool
- automake
- node
- debs:
- python-setuptools
- python3-dev
- python-virtualenv
- python-pip
- firefox
- automake
- libtool
- libreadline6
- libreadline6-dev
- libreadline-dev
- libsqlite3-dev
- libpq-dev
- libxml2
- libxml2-dev
- libssl-dev
- libbz2-dev
- wget
- curl
- llvm
- graphviz-dev
- libtiff4-dev
- libjpeg8-dev
- libfreetype6-dev
- liblcms1-dev
- libwebp-dev
- zlib1g-dev
- gettext
- python-dev
- build-essential

View File

@ -1,10 +0,0 @@
{% raw %}{% extends "base.yml" %}
{% block test %}
- engine: engine.py:ExecutionEngine
name: Stub {{ python_version }}
preconditions:
python_version: "{{ python_version }}"
scenario:
- Load website
- Pause
{% endblock %}{% endraw %}

View File

@ -0,0 +1,11 @@
firefox
libpq-dev
llvm
graphviz-dev
libtiff-dev
libjpeg8-dev
libfreetype6-dev
liblcms-dev
libwebp-dev
zlib1g-dev
gettext

View File

@ -0,0 +1,9 @@
# Test driven development settings
#
# Run with : hitch test . --settings tdd.settings
#
# Tests stop on first failure, pause and launch into IPython for debugging/interaction.
failfast: true
pause_on_failure: true
pause_on_success: true

View File

@ -1 +1,6 @@
"""
To understand why this file is here, please read:
http://cookiecutter-django.readthedocs.org/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
"""
# -*- coding: utf-8 -*-

View File

@ -1 +1,6 @@
"""
To understand why this file is here, please read:
http://cookiecutter-django.readthedocs.org/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
"""
# -*- coding: utf-8 -*-

View File

@ -1,4 +1,10 @@
"""
To understand why this file is here, please read:
http://cookiecutter-django.readthedocs.org/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

View File

@ -1 +1,6 @@
"""
To understand why this file is here, please read:
http://cookiecutter-django.readthedocs.org/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
"""
# -*- coding: utf-8 -*-

View File

@ -1,34 +1,38 @@
/* line 5, ../sass/project.scss */
/* These styles are generated from project.scss. */
.alert-debug {
color: black;
background-color: white;
border-color: #d6e9c6;
}
/* line 11, ../sass/project.scss */
.alert-info {
color: #3a87ad;
background-color: #d9edf7;
border-color: #bce8f1;
}
/* line 17, ../sass/project.scss */
.alert-success {
color: #468847;
background-color: #dff0d8;
border-color: #d6e9c6;
}
/* line 23, ../sass/project.scss */
.alert-warning {
color: black;
background-color: orange;
border-color: #d6e9c6;
}
/* line 29, ../sass/project.scss */
.alert-error {
color: #b94a48;
background-color: #f2dede;
border-color: #eed3d7;
}
/* This is a fix for the bootstrap4 alpha release */
@media (max-width: 47.9em) {
.navbar-nav .nav-item {
float: none;
width: 100%;
display: inline-block;
}
.navbar-nav .nav-item + .nav-item {
margin-left: 0;
}
.nav.navbar-nav.pull-xs-right {
float: none !important;
}
}
/* Display django-debug-toolbar.
See https://github.com/django-debug-toolbar/django-debug-toolbar/issues/742
and https://github.com/pydanny/cookiecutter-django/issues/317
*/
[hidden][style="display: block;"] {
display: block !important;
}

View File

@ -1,33 +1,51 @@
// project specific CSS goes here
// Alert colors
$white: #fff;
$mint-green: #d6e9c6;
$black: #000;
$pink: #f2dede;
$dark-pink: #eed3d7;
$red: #b94a48;
// bootstrap alert CSS, translated to the django-standard levels of
// debug, info, success, warning, error
.alert-debug {
color: black;
background-color: white;
border-color: #d6e9c6;
}
.alert-info {
color: #3a87ad;
background-color: #d9edf7;
border-color: #bce8f1;
}
.alert-success {
color: #468847;
background-color: #dff0d8;
border-color: #d6e9c6;
}
.alert-warning {
color: black;
background-color: orange;
border-color: #d6e9c6;
background-color: $white;
border-color: $mint-green;
color: $black;
}
.alert-error {
color: #b94a48;
background-color: #f2dede;
border-color: #eed3d7;
background-color: $pink;
border-color: $dark-pink;
color: $red;
}
// This is a fix for the bootstrap4 alpha release
@media (max-width: 47.9em) {
.navbar-nav .nav-item {
display: inline-block;
float: none;
width: 100%;
}
.navbar-nav .nav-item + .nav-item {
margin-left: 0;
}
.nav.navbar-nav.pull-xs-right {
float: none !important;
}
}
// Display django-debug-toolbar.
// See https://github.com/django-debug-toolbar/django-debug-toolbar/issues/742
// and https://github.com/pydanny/cookiecutter-django/issues/317
[hidden][style="display: block;"] {
display: block !important;
}

View File

@ -5,9 +5,10 @@ from celery import Celery
from django.apps import AppConfig
from django.conf import settings
if not settings.configured:
# set the default Django settings module for the 'celery' program.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local") # pragma: no cover
app = Celery('{{cookiecutter.repo_name}}')
@ -23,11 +24,39 @@ class CeleryConfig(AppConfig):
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS, force=True)
{% if cookiecutter.use_sentry == "y" -%}
if hasattr(settings, 'RAVEN_CONFIG'):
# Celery signal registration
from raven import Client as RavenClient
from raven.contrib.celery import register_signal as raven_register_signal
from raven.contrib.celery import register_logger_signal as raven_register_logger_signal
raven_client = RavenClient(dsn=settings.RAVEN_CONFIG['DSN'])
raven_register_logger_signal(raven_client)
raven_register_signal(raven_client)
{%- endif %}
{% if cookiecutter.use_opbeat == "y" -%}
if hasattr(settings, 'OPBEAT'):
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 register_handlers as opbeat_register_handlers
from opbeat.contrib.celery import register_signal as opbeat_register_signal
try:
opbeat_register_signal(opbeat_client)
except Exception as e:
opbeat_logger.exception('Failed installing celery hook: %s' % e)
if 'opbeat.contrib.django' in settings.INSTALLED_APPS:
opbeat_register_handlers()
{%- endif %}
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
print('Request: {0!r}'.format(self.request)) # pragma: no cover
{% else %}
# Use this as a starting point for your project with celery.
# If you are not using celery, you can remove this app
{% endif %}
{% endif -%}

View File

@ -1,7 +1,6 @@
{% raw %}{% extends "account/base.html" %}
{% load i18n %}
{% load url from future %}
{% load crispy_forms_tags %}
{% block head_title %}{% trans "Account" %}{% endblock %}

View File

@ -1,6 +1,5 @@
{% raw %}{% extends "account/base.html" %}
{% load url from future %}
{% load i18n %}
{% load account %}
@ -21,7 +20,7 @@
<form method="post" action="{% url 'account_confirm_email' confirmation.key %}">
{% csrf_token %}
<button class="submit" type="submit">{% trans 'Confirm' %}</button>
<button id="confirm-button" class="submit" type="submit">{% trans 'Confirm' %}</button>
</form>
{% else %}

View File

@ -2,7 +2,7 @@
{% load i18n %}
{% load account %}
{% load url from future %}
{% load socialaccount %}
{% load crispy_forms_tags %}
{% block head_title %}{% trans "Sign In" %}{% endblock %}
@ -12,8 +12,8 @@
<div class="row">
<div class="col-md-5">
<h2>{% trans "Sign In" %}</h2>
{% if socialaccount.providers %}
{% get_providers as socialaccount_providers %}
{% if socialaccount_providers %}
<p>{% blocktrans with site.name as site_name %}Please sign in with one
of your existing third party accounts. Or, <a href="{{ signup_url }}">sign up</a>
for a {{ site_name }} account and sign in below:{% endblocktrans %}</p>
@ -38,7 +38,7 @@
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
<button class="btn btn-primary" type="submit">{% trans "Sign In" %}</button>
<button id="sign-in-button" class="btn btn-primary" type="submit">{% trans "Sign In" %}</button>
<a class="button secondaryAction" href="{% url 'account_reset_password' %}">{% trans "Forgot Password?" %}</a>
</form>
</div>

View File

@ -1,6 +1,5 @@
{% raw %}{% extends "account/base.html" %}
{% load url from future %}
{% load i18n %}
{% block head_title %}{% trans "Sign Out" %}{% endblock %}

View File

@ -1,6 +1,5 @@
{% raw %}{% extends "account/base.html" %}
{% load url from future %}
{% load i18n %}
{% load crispy_forms_tags %}

View File

@ -1,6 +1,5 @@
{% raw %}{% extends "account/base.html" %}
{% load url from future %}
{% load i18n %}
{% block head_title %}{% trans "Change Password" %}{% endblock %}

View File

@ -1,6 +1,5 @@
{% raw %}{% extends "account/base.html" %}
{% load url from future %}
{% load i18n %}
{% load crispy_forms_tags %}
@ -21,7 +20,7 @@
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
<button class="btn btn-primary" type="submit">{% trans "Sign Up" %} &raquo;</button>
<button id="sign-up-button" class="btn btn-primary" type="submit">{% trans "Sign Up" %} &raquo;</button>
</form>
</div>
</div>

View File

@ -1,6 +1,5 @@
{% raw %}{% extends "account/base.html" %}
{% load url from future %}
{% load i18n %}
{% block head_title %}{% trans "Sign Up Closed" %}{% endblock %}

View File

@ -1,6 +1,5 @@
{% raw %}{% extends "account/base.html" %}
{% load url from future %}
{% load i18n %}
{% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %}

View File

@ -15,10 +15,7 @@
{% block css %}
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css">
<!-- Your stuff: Third-party css libraries go here -->
@ -27,51 +24,59 @@
{% endblock %}
{% block angular %}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
{% endblock %}
</head>
<body>
<div class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<div class="m-b">
<nav class="navbar navbar-dark navbar-static-top bg-inverse">
<div class="container">
<a class="navbar-brand" href="/">{% endraw %}{{ cookiecutter.project_name }}{% raw %}</a>
</div>
<button type="button" class="navbar-toggler hidden-sm-up pull-xs-right" data-toggle="collapse" data-target="#bs-navbar-collapse-1">
&#9776;
</button>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-navbar-collapse-1">
<div class="collapse navbar-toggleable-xs" id="bs-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="{% url 'home' %}">Home</a></li>
<li><a href="{% url 'about' %}">About</a></li>
<li class="nav-item">
<a class="nav-link" href="{% url 'home' %}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'about' %}">About</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<ul class="nav navbar-nav pull-xs-right">
{% if request.user.is_authenticated %}
<li><a href="{% url 'users:detail' request.user.username %}">{% trans "My Profile" %}</a></li>
<li><a href="{% url 'account_logout' %}">{% trans "Logout" %}</a></li>
<li class="nav-item">
<a class="nav-link" href="{% url 'users:detail' request.user.username %}">{% trans "My Profile" %}</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'account_logout' %}">{% trans "Logout" %}</a>
</li>
{% else %}
<li><a href="{% url 'account_signup' %}">{% trans "Sign Up" %}</a></li>
<li><a href="{% url 'account_login' %}">{% trans "Log In" %}</a></li>
<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 "Log In" %}</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>
</div>
<div class="container">
{% if messages %}
{% for message in messages %}
<div class="alert {% if message.tags %}alert-{{ message.tags }}"{% endif %}>{{ message }}</div>
<div class="alert {% if message.tags %}alert-{{ message.tags }}{% endif %}">{{ message }}</div>
{% endfor %}
{% endif %}
@ -88,10 +93,13 @@
<!-- Placed at the end of the document so the pages load faster -->
{% block javascript %}
<!-- Latest JQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<!-- Tether - a requirement for Bootstrap tooltips -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.2.0/js/tether.min.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script src="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.js"></script>
<!-- Your stuff: Third-party javascript libraries go here -->

View File

@ -17,4 +17,6 @@
</div>
</div>
{% endblock content %}{% endraw %}

View File

@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
from django.conf import settings
from allauth.account.adapter import DefaultAccountAdapter
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
class AccountAdapter(DefaultAccountAdapter):
def is_open_for_signup(self, request):
return getattr(settings, 'ACCOUNT_ALLOW_REGISTRATION', True)
class SocialAccountAdapter(DefaultSocialAccountAdapter):
def is_open_for_signup(self, request, sociallogin):
return getattr(settings, 'ACCOUNT_ALLOW_REGISTRATION', True)

View File

@ -0,0 +1,11 @@
import factory
class UserFactory(factory.django.DjangoModelFactory):
username = factory.Sequence(lambda n: 'user-{0}'.format(n))
email = factory.Sequence(lambda n: 'user-{0}@example.com'.format(n))
password = factory.PostGenerationMethodCall('set_password', 'password')
class Meta:
model = 'users.User'
django_get_or_create = ('username', )

View File

@ -4,7 +4,7 @@ from __future__ import absolute_import, unicode_literals
from django.core.urlresolvers import reverse
from django.views.generic import DetailView, ListView, RedirectView, UpdateView
from braces.views import LoginRequiredMixin
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import User