mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-07-29 01:09:50 +03:00
fix merge conflict issues
This commit is contained in:
commit
e4f2a83e6a
27
CHANGELOG.md
27
CHANGELOG.md
|
@ -2,6 +2,33 @@
|
|||
All enhancements and patches to Cookiecutter Django will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
##[2016-06-06]
|
||||
### Changed
|
||||
- Pin Bootstrap CSS and JS to v4.0.0-alpha.2, use minified versions
|
||||
|
||||
##[2016-06-05]
|
||||
### Added
|
||||
- Configurable admin for users (@pydanny, @jayfk, @dezoito)
|
||||
|
||||
##[2016-06-04]
|
||||
### Added
|
||||
- Let's Encrypt automation and instruction (@mjsisley and @chrisdev)
|
||||
|
||||
##[2016-06-03]
|
||||
### Added
|
||||
- Documentation for debugging with Docker (@mjsisley)
|
||||
- Apache 2 License option in `cookiecutter.json` (@dot2dotseurat)
|
||||
- Removed unnecessary version check from `pre_gen_project.py` (@suledev)
|
||||
- Add gulp alternative as a js task runner and fix navbar style issue (@viviangb and @xpostudio4)
|
||||
|
||||
### Deleted
|
||||
- AngularJS (@pydanny)
|
||||
- django-secure (@xpostudio4)
|
||||
|
||||
##[2016-06-02]
|
||||
### Added
|
||||
- Added better instructions for installing postgres on Mac OS X (@dot2dotseurat )
|
||||
|
||||
##[2016-05-22]
|
||||
### Added
|
||||
- Added instructions for copying backups from docker to host (@phiberjenz)
|
||||
|
|
|
@ -61,6 +61,7 @@ Listed in alphabetical order.
|
|||
Chris Franklin
|
||||
Chris Franklin `@hairychris`_
|
||||
Chris Pappalardo `@ChrisPappalardo`_
|
||||
Christopher Clarke `@chrisdev`_
|
||||
Collederas `@Collederas`_
|
||||
Cristian Vargas `@cdvv7788`_
|
||||
Cullen Rhodes `@c-rhodes`_
|
||||
|
@ -82,11 +83,13 @@ Listed in alphabetical order.
|
|||
Jens Nilsson `@phiberjenz`
|
||||
Julio Castillo `@juliocc`_
|
||||
Kaido Kert `@kaidokert`_
|
||||
kappataumu `@kappataumu`_ @kappataumu
|
||||
Kaveh `@ka7eh`_
|
||||
Kevin A. Stone
|
||||
Kevin Ndung'u `@kevgathuku`_
|
||||
Krzysztof Szumny `@noisy`_
|
||||
Krzysztof Żuraw `@krzysztofzuraw`_
|
||||
Leonardo Jimenez `@xpostudio4`_
|
||||
Lin Xianyi `@iynaix`_
|
||||
Luis Nell `@originell`_
|
||||
Lukas Klein
|
||||
|
@ -96,6 +99,8 @@ Listed in alphabetical order.
|
|||
Matt Linares
|
||||
Matt Menzenski `@menzenski`_
|
||||
Matt Warren `@mfwarren`_
|
||||
Matthew Sisley `@mjsisley`_
|
||||
Meghan Heintz `@dot2dotseurat`_
|
||||
mozillazg `@mozillazg`_
|
||||
Pablo `@oubiga`_
|
||||
Raphael Pierzina `@hackebrot`_
|
||||
|
@ -106,16 +111,17 @@ Listed in alphabetical order.
|
|||
stepmr `@stepmr`_
|
||||
Sławek Ehlert `@slafs`_
|
||||
Srinivas Nyayapati `@shireenrao`_
|
||||
Sule Marshall `@suledev`_
|
||||
Taylor Baldwin
|
||||
Théo Segonds `@show0k`_
|
||||
Tom Atkins `@knitatoms`_
|
||||
Tom Offermann
|
||||
Travis McNeill `@Travistock`_ @tavistock_esq
|
||||
Travis McNeill `@Travistock`_ @tavistock_esq
|
||||
Vitaly Babiy
|
||||
Vivian Guillen `@viviangb`_
|
||||
Yaroslav Halchenko
|
||||
========================== ============================ ==============
|
||||
|
||||
.. _@dezoito: https://github.com/dezoito
|
||||
.. _@a7p: https://github.com/a7p
|
||||
.. _@ad-m: https://github.com/ad-m
|
||||
.. _@aeikenberry: https://github.com/aeikenberry
|
||||
|
@ -125,6 +131,7 @@ Listed in alphabetical order.
|
|||
.. _@areski: https://github.com/areski
|
||||
.. _@arruda: https://github.com/arruda
|
||||
.. _@bloodpet: https://github.com/bloodpet
|
||||
.. _@blopker: https://github.com/blopker
|
||||
.. _@bogdal: https://github.com/bogdal
|
||||
.. _@burhan: https://github.com/burhan
|
||||
.. _@c-rhodes: https://github.com/c-rhodes
|
||||
|
@ -132,9 +139,12 @@ Listed in alphabetical order.
|
|||
.. _@catherinedevlin: https://github.com/catherinedevlin
|
||||
.. _@ccurvey: https://github.com/ccurvey
|
||||
.. _@cdvv7788: https://github.com/cdvv7788
|
||||
.. _@chrisdev: https://github.com/chrisdev
|
||||
.. _@ChrisPappalardo: https://github.com/ChrisPappalardo
|
||||
.. _@Collederas: https://github.com/Collederas
|
||||
.. _@ddiazpinto: https://github.com/ddiazpinto
|
||||
.. _@dezoito: https://github.com/dezoito
|
||||
.. _@dot2dotseurat: https://github.com/dot2dotseurat
|
||||
.. _@dsclementsen: https://github.com/dsclementsen
|
||||
.. _@epileptic-fish: https://gihub.com/epileptic-fish
|
||||
.. _@eraldo: https://github.com/eraldo
|
||||
|
@ -153,26 +163,33 @@ Listed in alphabetical order.
|
|||
.. _@jvanbrug: https://github.com/jvanbrug
|
||||
.. _@ka7eh: https://github.com/ka7eh
|
||||
.. _@kaidokert: https://github.com/kaidokert
|
||||
.. _@kappataumu: https://github.com/kappataumu
|
||||
.. _@kevgathuku: https://github.com/kevgathuku
|
||||
.. _@knitatoms: https://github.com/knitatoms
|
||||
.. _@krzysztofzuraw: https://github.com/krzysztofzuraw
|
||||
.. _@MathijsHoogland: https://github.com/MathijsHoogland
|
||||
.. _@menzenski: https://github.com/menzenski
|
||||
.. _@mfwarren: https://github.com/mfwarren
|
||||
.. _@mjsisley: https://github.com/mjsisley
|
||||
.. _@mozillazg: https://github.com/mozillazg
|
||||
.. _@noisy: https://github.com/noisy
|
||||
.. _@originell: https://github.com/originell
|
||||
.. _@oubiga: https://github.com/oubiga
|
||||
.. _@romanosipenko: https://github.com/romanosipenko
|
||||
.. _@raonyguimaraes: https://github.com/raonyguimaraes
|
||||
.. _@romanosipenko: https://github.com/romanosipenko
|
||||
.. _@shireenrao: https://github.com/shireenrao
|
||||
.. _@show0k: https://github.com/show0k
|
||||
.. _@siauPatrick: https://github.com/siauPatrick
|
||||
.. _@shireenrao: https://github.com/shireenrao
|
||||
.. _@slafs: https://github.com/slafs
|
||||
.. _@stepmr: https://github.com/stepmr
|
||||
.. _@suledev: https://github.com/suledev
|
||||
.. _@Travistock: https://github.com/Tavistock
|
||||
.. _@trungdong: https://github.com/trungdong
|
||||
.. _@viviangb: httpsL//github.com/viviangb
|
||||
.. _@xpostudio4: https://github.com/xpostudio4
|
||||
.. _@yunti: https://github.com/yunti
|
||||
.. _@zcho: https://github.com/zcho
|
||||
.. _@noisy: https://github.com/noisy
|
||||
|
||||
Special Thanks
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
|
|
43
LICENSE
43
LICENSE
|
@ -1,4 +1,17 @@
|
|||
Copyright (c) 2013-2016, Daniel Greenfeld
|
||||
{% if cookiecutter.open_source_license == 'MIT' %}
|
||||
MIT License
|
||||
|
||||
Copyright (c) {% now 'local', '%Y' %}, {{ cookiecutter.full_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.open_source_license == 'BSD' %}
|
||||
BSD License
|
||||
|
||||
Copyright (c) {% now 'local', '%Y' %}, {{ cookiecutter.full_name }}
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
@ -11,9 +24,9 @@ are permitted provided that the following conditions are met:
|
|||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
* Neither the name of Cookiecutter Django nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
* Neither the name of {{ cookiecutter.project_name }} nor the names of its
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
|
@ -21,7 +34,25 @@ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIME
|
|||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
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.
|
||||
{% elif cookiecutter.open_source_license == 'Apache Software License 2.0' %}
|
||||
Apache Software License 2.0
|
||||
|
||||
Copyright (c) {% now 'local', '%Y' %}, {{ cookiecutter.full_name }}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
{% endif %}
|
||||
|
|
16
README.rst
16
README.rst
|
@ -14,9 +14,12 @@ Cookiecutter Django
|
|||
|
||||
Powered by Cookiecutter_, Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly.
|
||||
|
||||
* Documentation: https://cookiecutter-django.readthedocs.io
|
||||
* See Troubleshooting_ for common errors and obstacles
|
||||
|
||||
.. _cookiecutter: https://github.com/audreyr/cookiecutter
|
||||
|
||||
**Warning**: if you get the error "jinja2.exceptions.TemplateSyntaxError: Encountered unknown tag 'now'." , please upgrade your cookiecutter version to >= 1.4 (see issue # 528_ )
|
||||
.. _Troubleshooting: https://cookiecutter-django.readthedocs.io/en/latest/troubleshooting.html
|
||||
|
||||
.. _528: https://github.com/pydanny/cookiecutter-django/issues/528#issuecomment-212650373
|
||||
|
||||
|
@ -26,7 +29,6 @@ Features
|
|||
* For Django 1.9
|
||||
* Renders Django projects with 100% starting test coverage
|
||||
* Twitter Bootstrap_ v4.0.0 - alpha_
|
||||
* AngularJS_
|
||||
* 12-Factor_ based settings via django-environ_
|
||||
* Optimized development and production settings
|
||||
* Registration via django-allauth_
|
||||
|
@ -55,7 +57,6 @@ Optional Integrations
|
|||
|
||||
.. _alpha: http://blog.getbootstrap.com/2015/08/19/bootstrap-4-alpha/
|
||||
.. _Bootstrap: https://github.com/twbs/bootstrap
|
||||
.. _AngularJS: https://github.com/angular/angular.js
|
||||
.. _django-environ: https://github.com/joke2k/django-environ
|
||||
.. _12-Factor: http://12factor.net/
|
||||
.. _django-allauth: https://github.com/pennersr/django-allauth
|
||||
|
@ -99,8 +100,6 @@ You'll be prompted for some values. Provide them, then a Django project will be
|
|||
|
||||
**Warning**: After this point, change 'Daniel Greenfeld', 'pydanny', etc to your own information.
|
||||
|
||||
**Warning**: project_slug must be a valid Python module name or you will have issues on imports.
|
||||
|
||||
Answer the prompts with your own desired options_. For example::
|
||||
|
||||
Cloning into 'cookiecutter-django'...
|
||||
|
@ -117,13 +116,10 @@ Answer the prompts with your own desired options_. For example::
|
|||
domain_name [example.com]: myreddit.com
|
||||
version [0.1.0]: 0.0.1
|
||||
timezone [UTC]: America/Los_Angeles
|
||||
now [2016/03/01]: 2016/03/05
|
||||
year [2016]:
|
||||
use_whitenoise [y]: n
|
||||
use_celery [n]: y
|
||||
use_mailhog [n]: n
|
||||
use_sentry [n]: y
|
||||
use_newrelic [n]: y
|
||||
use_sentry_for_error_reporting [y]: y
|
||||
use_opbeat [n]: y
|
||||
use_pycharm [n]: y
|
||||
windows [n]: n
|
||||
|
@ -131,8 +127,8 @@ Answer the prompts with your own desired options_. For example::
|
|||
use_docker [y]: y
|
||||
use_heroku [n]: n
|
||||
use_grunt [n]: y
|
||||
use_angular [n]: n
|
||||
use_precommit_hooks [n]: n
|
||||
|
||||
Select open_source_license:
|
||||
1 - MIT
|
||||
2 - BSD
|
||||
|
|
|
@ -7,21 +7,18 @@
|
|||
"domain_name": "example.com",
|
||||
"version": "0.1.0",
|
||||
"timezone": "UTC",
|
||||
"now": "{% now 'local' %}",
|
||||
"year": "{{ cookiecutter.now[:4] }}",
|
||||
"use_whitenoise": "y",
|
||||
"use_celery": "n",
|
||||
"use_mailhog": "n",
|
||||
"use_sentry": "n",
|
||||
"use_newrelic": "n",
|
||||
"use_sentry_for_error_reporting": "y",
|
||||
"use_opbeat": "n",
|
||||
"use_pycharm": "n",
|
||||
"windows": "n",
|
||||
"use_python2": "n",
|
||||
"use_docker": "y",
|
||||
"use_heroku": "n",
|
||||
"use_grunt": "n",
|
||||
"use_angular": "n",
|
||||
"js_task_runner": ["Gulp", "Grunt", "None"],
|
||||
"use_precommit_hooks": "n",
|
||||
"open_source_license": ["MIT", "BSD", "Not open source"]
|
||||
"use_lets_encrypt": "n",
|
||||
"open_source_license": ["MIT", "BSD", "Apache Software License 2.0", "Not open source"]
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ master_doc = 'index'
|
|||
|
||||
# General information about the project.
|
||||
project = 'Cookiecutter Django'
|
||||
copyright = '2013-{}, Daniel Roy Greenfeld'.format(now.year)
|
||||
copyright = '2013-{% now 'utc', '%Y' %}, 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
|
||||
|
|
|
@ -110,3 +110,47 @@ To get the status, run::
|
|||
If you have errors, you can always check your stack with `docker-compose`. Switch to your projects root directory and run::
|
||||
|
||||
docker-compose ps
|
||||
|
||||
If you are using certbot for https, you must do the following before running anything with docker-compose:
|
||||
|
||||
Replace dhparam.pem.example with a generated dhparams.pem file before running anything with docker-compose. You can generate this on ubuntu or OS X by running the following in the project root:
|
||||
|
||||
::
|
||||
|
||||
$ openssl dhparam -out /path/to/project/compose/nginx/dhparams.pem 2048
|
||||
|
||||
If you would like to add additional subdomains to your certificate, you must add additional parameters to the certbot command in the `docker-compose.yml` file:
|
||||
|
||||
Replace:
|
||||
|
||||
::
|
||||
|
||||
command: bash -c "sleep 6 && certbot certonly -n --standalone -d {{ cookiecutter.domain_name }} --text --agree-tos --email mjsisley@relawgo.com --server https://acme-v01.api.letsencrypt.org/directory --rsa-key-size 4096 --verbose --keep-until-expiring --standalone-supported-challenges http-01"
|
||||
|
||||
With:
|
||||
|
||||
::
|
||||
|
||||
command: bash -c "sleep 6 && certbot certonly -n --standalone -d {{ cookiecutter.domain_name }} -d www.{{ cookiecutter.domain_name }} -d etc.{{ cookiecutter.domain_name }} --text --agree-tos --email {{ cookiecutter.email }} --server https://acme-v01.api.letsencrypt.org/directory --rsa-key-size 4096 --verbose --keep-until-expiring --standalone-supported-challenges http-01"
|
||||
|
||||
Please be cognizant of Certbot/Letsencrypt certificate requests limits when getting this set up. The provide a test server that does not count against the limit while you are getting set up.
|
||||
|
||||
The certbot certificates expire after 3 months.
|
||||
If you would like to set up autorenewal of your certificates, the following commands can be put into a bash script:
|
||||
|
||||
::
|
||||
|
||||
#!/bin/bash
|
||||
cd <project directory>
|
||||
docker-compose run certbot bash -c "sleep 6 && certbot certonly --standalone -d {{ cookiecutter.domain_name }} --text --agree-tos --email {{ cookiecutter.email }} --server https://acme-v01.api.letsencrypt.org/directory --rsa-key-size 4096 --verbose --keep-until-expiring --standalone-supported-challenges http-01"
|
||||
docker exec pearl_nginx_1 nginx -s reload
|
||||
|
||||
And then set a cronjob by running `crontab -e` and placing in it (period can be adjusted as desired):
|
||||
|
||||
0 4 * * 1 /path/to/bashscript/renew_certbot.sh
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -141,3 +141,46 @@ If you want to run the stack in detached mode (in the background), use the ``-d`
|
|||
::
|
||||
|
||||
$ docker-compose -f dev.yml up -d
|
||||
|
||||
Debugging
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
ipdb
|
||||
"""""
|
||||
|
||||
If you are using the following within your code to debug:
|
||||
|
||||
::
|
||||
|
||||
import ipdb; ipdb.set_trace()
|
||||
|
||||
Then you may need to run the following for it to work as desired:
|
||||
|
||||
::
|
||||
|
||||
$ docker-compose run -f dev.yml --service-ports django
|
||||
|
||||
|
||||
django-debug-toolbar
|
||||
""""""""""""""""""""
|
||||
|
||||
In order for django-debug-toolbar to work with docker you need to add your docker-machine ip address (the output of `Get the IP ADDRESS`_) to INTERNAL_IPS in local.py
|
||||
|
||||
|
||||
.. May be a better place to put this, as it is not Docker specific.
|
||||
|
||||
You may need to add the following to your css in order for the django-debug-toolbar to be visible (this applies whether Docker is being used or not):
|
||||
|
||||
.. code-block:: css
|
||||
|
||||
/* Override Bootstrap 4 styling on Django Debug Toolbar */
|
||||
#djDebug[hidden], #djDebug [hidden] {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
#djDebug [hidden][style='display: none;'] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -9,20 +9,32 @@ The steps below will get you up and running with a local development environment
|
|||
* virtualenv
|
||||
* PostgreSQL
|
||||
|
||||
First make sure to create and activate a virtualenv_, then open a terminal at the project root and install the os dependencies::
|
||||
First make sure to create and activate a virtualenv_.
|
||||
|
||||
$ sudo ./install_os_dependencies.sh install
|
||||
.. _virtualenv: http://docs.python-guide.org/en/latest/dev/virtualenvs/
|
||||
|
||||
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 `[project_slug]` is what value you entered for your project's `project_slug`::
|
||||
|
||||
$ createdb [project_slug]
|
||||
|
||||
You can now run the usual Django ``migrate`` and ``runserver`` commands::
|
||||
|
||||
$ python manage.py migrate
|
||||
$ python manage.py runserver
|
||||
|
||||
At this point you can take a break from setup and start getting to know the files in the project.
|
||||
|
||||
But if you want to go further with setup, read on.
|
||||
|
||||
(Note: the following sections still need to be revised)
|
||||
|
||||
Setting Up Env Vars for Production
|
||||
-----------------------------------
|
||||
|
||||
`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 rename env.example to .env and then compose a definition for ``DATABASE_URL`` as shown below and add it to the .env file:
|
||||
|
||||
.. parsed-literal::
|
||||
|
@ -31,12 +43,8 @@ Then, create a PostgreSQL database with the following command, where `[project_s
|
|||
|
||||
.. _django-environ: http://django-environ.readthedocs.io
|
||||
|
||||
You can now run the usual Django ``migrate`` and ``runserver`` commands::
|
||||
|
||||
$ python manage.py migrate
|
||||
$ python manage.py runserver
|
||||
|
||||
**Setup your email backend**
|
||||
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`_
|
||||
|
||||
|
@ -85,5 +93,3 @@ The base app will now run as it would with the usual ``manage.py runserver`` but
|
|||
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!!!
|
||||
|
|
|
@ -14,7 +14,6 @@ Contents:
|
|||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
project-generation-options
|
||||
developing-locally
|
||||
developing-locally-docker
|
||||
|
@ -25,6 +24,8 @@ Contents:
|
|||
deployment-on-heroku
|
||||
deployment-with-docker
|
||||
faq
|
||||
troubleshooting
|
||||
my-favorite-cookie
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
|
17
docs/installing_postgres.rst
Normal file
17
docs/installing_postgres.rst
Normal file
|
@ -0,0 +1,17 @@
|
|||
PostgreSQL Installation Basics
|
||||
==============================
|
||||
|
||||
.. index:: pip, virtualenv, PostgreSQL
|
||||
|
||||
The steps below will get you up and running with PostgreSQL. This assumes you have pip and virtualenv_ installed.
|
||||
|
||||
.. _virtualenv: http://docs.python-guide.org/en/latest/dev/virtualenvs/
|
||||
|
||||
On Mac
|
||||
|
||||
Install PostgreSQLapp_ from the browser and move PostGresSQL into your applications folder. Then install PostgreSQL from HomeBrew_.
|
||||
|
||||
$ brew install postgres
|
||||
|
||||
.. _PostgreSQLapp: http://postgresapp.com/
|
||||
.. _HomeBrew: http://brew.sh/
|
100
docs/my-favorite-cookie.rst
Normal file
100
docs/my-favorite-cookie.rst
Normal file
|
@ -0,0 +1,100 @@
|
|||
************************************************
|
||||
Creating your first app with Cookiecutter-Django
|
||||
************************************************
|
||||
|
||||
This tutorial will show you how to build a simple app using the `Cookiecutter Django <https://github.com/pydanny/cookiecutter-django>`_ templating system. We'll be building a cookie polling app to determine the most popular flavor of cookie.
|
||||
|
||||
Developers who have never used Django will learn the basics of creating a Django app; developers who are experienced with Django will learn how to set up a project within the Cookiecutter system. While many Django tutorials use the default SQLite database, Cookiecutter Django uses PostGres only, so we'll have you install and use that.
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
This tutorial was written on Windows 10 using `git bash <https://git-for-windows.github.io/>`_; alternate instructions for Mac OS and Linux will be provided when needed. Any Linux-style shell should work for the following commands.
|
||||
|
||||
You should have your preferred versions of `Python <https://www.python.org/downloads/>`_
|
||||
and `Django <https://www.djangoproject.com/download/>`_ installed. Use the latest stable versions if you have no preference.
|
||||
|
||||
You should have `Virtualenv <https://virtualenv.pypa.io/en/stable/>`_ and `Cookiecutter <https://github.com/pydanny/cookiecutter-django/>`_ installed:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
$ pip install virtualenv
|
||||
$ pip install cookiecutter
|
||||
|
||||
You should also have `PostgreSQL <https://www.postgresql.org/download/>`_ installed on your machine--just download and run the installer for your OS. The install menu will prompt you for a password, which you'll use when creating the project's database.
|
||||
|
||||
|
||||
Instructions
|
||||
============
|
||||
|
||||
1. **Setup** -- how to set up a virtual environment
|
||||
2. **Cookiecutter** -- use Cookiecutter to initialize a project with your own customized information.
|
||||
3. **Building the App** -- creating the My Favorite Cookie application.
|
||||
|
||||
============
|
||||
1. Setup
|
||||
============
|
||||
|
||||
Virtual Environment
|
||||
"""""""""""""""""""
|
||||
|
||||
Create a virtual environment for your project. Cookiecutter will install a bunch of dependencies for you automatically; using a virtualenv will prevent this from interfering with your other work.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
$ virtualenv c:/.virtualenvs/cookie_polls
|
||||
|
||||
Replace ``c:/.virtualenvs`` with the path to your own ``.virtualenvs`` folder.
|
||||
|
||||
Activate the virtual environment by calling ``source`` on the ``activate`` shell script . On Windows you'll call this from the virtualenv's ``scripts`` folder:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
$ source /path/to/.virtualenvs/cookie_polls/scripts/activate
|
||||
|
||||
On other operating systems, it'll be found in the ``bin`` folder.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
$ source /path/to/.virtualenvs/cookie_polls/bin/activate
|
||||
|
||||
You'll know the virtual environment is active because its name will appear in parentheses before the command prompt. When you're done with this project, you can leave the virtual environment with the ``deactivate`` command.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
(cookie_polls)
|
||||
$ deactivate
|
||||
|
||||
|
||||
Now you're ready to create your project using Cookiecutter.
|
||||
|
||||
|
||||
===============
|
||||
2. Cookiecutter
|
||||
===============
|
||||
|
||||
Django developers may be familiar with the ``startproject`` command, which initializes the directory structure and required files for a bare-bones Django project. While this is fine when you're just learning Django for the first time, it's not great for a real production app. Cookiecutter takes care of a lot of standard tasks for you, including installing software dependencies, setting up testing files, and including and organizing common libraries like Bootstrap and AngularJS. It also generates a software license and a README.
|
||||
|
||||
Change directories into the folder where you want your project to live, and run ``cookiecutter`` followed by the URL of Cookiecutter's Github repo.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
$ cd /my/project/folder
|
||||
(cookie_polls)
|
||||
my/project/folder
|
||||
$ cookiecutter https://github.com/pydanny/cookiecutter-django
|
||||
|
||||
This will prompt you for a bunch of values specific to your project. Press "enter" without typing anything to use the default values, which are shown in [brackets] after the question. You can learn about all the different options `here, <http://cookiecutter-django.readthedocs.io/en/latest/project-generation-options.html>`_ but for now we'll use the defaults for everything but your name, your email, the project's name, and the project's description.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
project_name [project_name]: My Favorite Cookie
|
||||
project_slug [My_Favorite_Cookie]:
|
||||
author_name [Your Name]: Emily Cain
|
||||
email [Your email]: contact@emcain.net
|
||||
description [A short description of the project.]: Poll your friends to determine the most popular cookie.
|
||||
|
||||
Then hit "enter" to use the default values for everything else.
|
||||
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ use_mailhog [n]
|
|||
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]
|
||||
use_sentry_for_error_reporting [n]
|
||||
Whether to use Sentry_ to log errors from your project.
|
||||
|
||||
windows [n]
|
||||
|
|
9
docs/troubleshooting.rst
Normal file
9
docs/troubleshooting.rst
Normal file
|
@ -0,0 +1,9 @@
|
|||
Troubleshooting
|
||||
=====================================
|
||||
|
||||
This page contains some advice about errors and problems commonly encountered during the development of Cookiecutter Django applications.
|
||||
|
||||
#. If you get the error ``jinja2.exceptions.TemplateSyntaxError: Encountered unknown tag 'now'.`` , please upgrade your cookiecutter version to >= 1.4 (see issue # 528_ )
|
||||
#. ``project_slug`` must be a valid Python module name or you will have issues on imports.
|
||||
|
||||
.. _528: https://github.com/pydanny/cookiecutter-django/issues/528#issuecomment-212650373
|
|
@ -82,6 +82,11 @@ def make_secret_key(project_directory):
|
|||
set_secret_key(env_file)
|
||||
|
||||
|
||||
def remove_file(file_name):
|
||||
if os.path.exists(file_name):
|
||||
os.remove(file_name)
|
||||
|
||||
|
||||
def remove_task_app(project_directory):
|
||||
"""Removes the taskapp if celery isn't going to be used"""
|
||||
# Determine the local_setting_file_location
|
||||
|
@ -118,9 +123,8 @@ def remove_heroku_files():
|
|||
Removes files needed for heroku if it isn't going to be used
|
||||
"""
|
||||
for filename in ["app.json", "Procfile", "requirements.txt", "runtime.txt"]:
|
||||
os.remove(os.path.join(
|
||||
PROJECT_DIRECTORY, filename
|
||||
))
|
||||
file_name = os.path.join(PROJECT_DIRECTORY, filename)
|
||||
remove_file(file_name)
|
||||
|
||||
|
||||
def remove_docker_files():
|
||||
|
@ -141,11 +145,38 @@ def remove_grunt_files():
|
|||
"""
|
||||
Removes files needed for grunt if it isn't going to be used
|
||||
"""
|
||||
for filename in ["Gruntfile.js", "package.json"]:
|
||||
for filename in ["Gruntfile.js"]:
|
||||
os.remove(os.path.join(
|
||||
PROJECT_DIRECTORY, filename
|
||||
))
|
||||
|
||||
def remove_gulp_files():
|
||||
"""
|
||||
Removes files needed for grunt if it isn't going to be used
|
||||
"""
|
||||
for filename in ["gulpfile.js"]:
|
||||
os.remove(os.path.join(
|
||||
PROJECT_DIRECTORY, filename
|
||||
))
|
||||
|
||||
def remove_packageJSON_file():
|
||||
"""
|
||||
Removes files needed for grunt if it isn't going to be used
|
||||
"""
|
||||
for filename in ["package.json"]:
|
||||
os.remove(os.path.join(
|
||||
PROJECT_DIRECTORY, filename
|
||||
))
|
||||
|
||||
def remove_certbot_files():
|
||||
"""
|
||||
Removes files needed for certbot if it isn't going to be used
|
||||
"""
|
||||
nginx_dir_location = os.path.join(PROJECT_DIRECTORY, 'compose/nginx')
|
||||
for filename in ["nginx-secure.conf", "start.sh", "dhparams.example.pem"]:
|
||||
file_name = os.path.join(nginx_dir_location, filename)
|
||||
remove_file(file_name)
|
||||
|
||||
# IN PROGRESS
|
||||
# def copy_doc_files(project_directory):
|
||||
# cookiecutters_dir = DEFAULT_CONFIG['cookiecutters_dir']
|
||||
|
@ -183,29 +214,45 @@ if '{{ cookiecutter.use_heroku }}'.lower() != 'y':
|
|||
if '{{ cookiecutter.use_docker }}'.lower() != 'y':
|
||||
remove_docker_files()
|
||||
|
||||
# 6. Removes all grunt files if it isn't going to be used
|
||||
if '{{ cookiecutter.use_grunt }}'.lower() != 'y':
|
||||
# 6. Removes all JS task manager files if it isn't going to be used
|
||||
if '{{ cookiecutter.js_task_runner}}'.lower() == 'gulp':
|
||||
remove_grunt_files()
|
||||
elif '{{ cookiecutter.js_task_runner}}'.lower() == 'grunt':
|
||||
remove_gulp_files()
|
||||
else:
|
||||
remove_gulp_files()
|
||||
remove_grunt_files()
|
||||
remove_packageJSON_file()
|
||||
|
||||
# 7. Display a warning if use_docker and use_grunt are selected. Grunt isn't supported by our
|
||||
# docker config atm.
|
||||
if '{{ cookiecutter.use_grunt }}'.lower() == 'y' and '{{ cookiecutter.use_docker }}'.lower() == 'y':
|
||||
# 7. Removes all certbot/letsencrypt files if it isn't going to be used
|
||||
if '{{ cookiecutter.use_lets_encrypt }}'.lower() != 'y':
|
||||
remove_certbot_files()
|
||||
|
||||
# 8. Display a warning if use_docker and use_grunt are selected. Grunt isn't
|
||||
# supported by our docker config atm.
|
||||
if '{{ cookiecutter.js_task_runner }}'.lower() in ['grunt', 'gulp'] and '{{ cookiecutter.use_docker }}'.lower() == 'y':
|
||||
print(
|
||||
"You selected to use docker and grunt. This is NOT supported out of the box for now. You "
|
||||
"You selected to use docker and a JS task runner. This is NOT supported out of the box for now. You "
|
||||
"can continue to use the project like you normally would, but you will need to add a "
|
||||
" grunt service to your docker configuration manually."
|
||||
"js task runner service to your docker configuration manually."
|
||||
)
|
||||
|
||||
# 7. Display a warning if use_docker and use_mailhog are selected. Mailhog isn't supported by our
|
||||
# docker config atm.
|
||||
if '{{ cookiecutter.use_mailhog }}'.lower() == 'y' and '{{ cookiecutter.use_docker }}'.lower() == 'y':
|
||||
# 9. Removes the certbot/letsencrypt files and display a warning if use_lets_encrypt is selected and use_docker isn't.
|
||||
if '{{ cookiecutter.use_lets_encrypt }}'.lower() == 'y' and '{{ cookiecutter.use_docker }}'.lower() != 'y':
|
||||
remove_certbot_files()
|
||||
print(
|
||||
"You selected to use docker and mailhog. This is NOT supported out of the box for now. You"
|
||||
" can continue to use the project like you normally would, but you will need to add a "
|
||||
" mailhog service to your docker configuration manually."
|
||||
"You selected to use Let's Encrypt and didn't select to use docker. This is NOT supported out of the box for now. You "
|
||||
"can continue to use the project like you normally would, but Let's Encrypt files have been included."
|
||||
)
|
||||
|
||||
# 8. If pre-commit hooks aren't used, remove pre-commit yaml file
|
||||
# 10. Directs the user to the documentation if certbot and docker are selected.
|
||||
if '{{ cookiecutter.use_lets_encrypt }}'.lower() == 'y' and '{{ cookiecutter.use_docker }}'.lower() == 'y':
|
||||
print(
|
||||
"You selected to use Let's Encrypt, please see the documentation for instructions on how to use this in production. "
|
||||
"You must generate a dhparams.pem file before running docker-compose in a production environment."
|
||||
)
|
||||
|
||||
# 11. If pre-commit hooks aren't used, remove pre-commit yaml file
|
||||
if '{{ cookiecutter.use_precommit_hooks }}'.lower() != 'y':
|
||||
remove_pre_commit_file()
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import cookiecutter
|
||||
|
||||
project_slug = '{{ cookiecutter.project_slug }}'
|
||||
|
||||
if hasattr(project_slug, 'isidentifier'):
|
||||
assert project_slug.isidentifier(), 'Project slug should be valid Python identifier!'
|
||||
|
||||
assert cookiecutter.__version__ > '1.3.0', 'Please upgrade your Cookiecutter installation'
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ sh==1.11
|
|||
binaryornot==0.4.0
|
||||
|
||||
# Testing
|
||||
pytest==2.9.1
|
||||
pytest==2.9.2
|
||||
pep8==1.7.0
|
||||
pyflakes==1.2.3
|
||||
tox==2.3.1
|
||||
|
|
|
@ -22,8 +22,6 @@ def context():
|
|||
'domain_name': 'example.com',
|
||||
'version': '0.1.0',
|
||||
'timezone': 'UTC',
|
||||
'now': '2015/01/13',
|
||||
'year': '2015'
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% if cookiecutter.open_source_license == 'MIT' %}
|
||||
The MIT License (MIT)
|
||||
Copyright (c) {{ cookiecutter.year }}, {{ cookiecutter.author_name }}
|
||||
Copyright (c) {% now 'utc', '%Y' %}, {{ 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:
|
||||
|
||||
|
@ -8,7 +8,7 @@ The above copyright notice and this permission notice shall be included in all c
|
|||
|
||||
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.open_source_license == 'BSD' %}
|
||||
Copyright (c) {{ cookiecutter.year }}, {{ cookiecutter.author_name }}
|
||||
Copyright (c) {% now 'utc', '%Y' %}, {{ cookiecutter.author_name }}
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
|
|
|
@ -1,4 +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.project_slug}}.taskapp --loglevel=info
|
||||
worker: celery worker --app={{cookiecutter.project_slug}}.taskapp --loglevel=info
|
||||
{%- endif %}
|
||||
|
|
|
@ -104,12 +104,12 @@ The email server will exit when you exit the Grunt task on the CLI with Ctrl+C.
|
|||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if cookiecutter.use_sentry == "y" %}
|
||||
{% if cookiecutter.use_sentry_for_error_reporting == "y" %}
|
||||
|
||||
Sentry
|
||||
^^^^^^
|
||||
|
||||
Sentry is an error logging aggregator service. You can sign up for a free account at http://getsentry.com or download and host it yourself.
|
||||
Sentry is an error logging aggregator service. You can sign up for a free account at https://getsentry.com/signup/?code=cookiecutter or download and host it yourself.
|
||||
The system is setup with reasonable defaults, including 404 logging and integration with the WSGI application.
|
||||
|
||||
You must set the DSN url in production.
|
||||
|
|
|
@ -20,12 +20,8 @@
|
|||
"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 %}
|
||||
"DJANGO_MAILGUN_API_KEY": ""{% if cookiecutter.use_sentry_for_error_reporting == "y" -%},
|
||||
"DJANGO_SENTRY_DSN": ""{%- endif %}
|
||||
},
|
||||
"scripts": {
|
||||
"postdeploy": "python manage.py migrate"
|
||||
|
|
|
@ -1,2 +1,8 @@
|
|||
FROM nginx:latest
|
||||
ADD nginx.conf /etc/nginx/nginx.conf
|
||||
ADD nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
{% if cookiecutter.use_lets_encrypt == 'y' and cookiecutter.use_docker == 'y' %}
|
||||
ADD start.sh /start.sh
|
||||
ADD nginx-secure.conf /etc/nginx/nginx-secure.conf
|
||||
ADD dhparams.pem /etc/ssl/private/dhparams.pem
|
||||
{% endif %}
|
||||
|
|
3
{{cookiecutter.project_slug}}/compose/nginx/dhparams.example.pem
Executable file
3
{{cookiecutter.project_slug}}/compose/nginx/dhparams.example.pem
Executable file
|
@ -0,0 +1,3 @@
|
|||
-----BEGIN DH PARAMETERS-----
|
||||
EXAMPLE_FILE
|
||||
-----END DH PARAMETERS-----
|
92
{{cookiecutter.project_slug}}/compose/nginx/nginx-secure.conf
Executable file
92
{{cookiecutter.project_slug}}/compose/nginx/nginx-secure.conf
Executable file
|
@ -0,0 +1,92 @@
|
|||
user nginx;
|
||||
worker_processes 1;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
proxy_headers_hash_bucket_size 52;
|
||||
|
||||
gzip on;
|
||||
|
||||
upstream app {
|
||||
server django:5000;
|
||||
}
|
||||
server {
|
||||
listen 80;
|
||||
server_name ___my.example.com___ www.___my.example.com___;
|
||||
|
||||
location /.well-known/acme-challenge {
|
||||
proxy_pass http://___LETSENCRYPT_IP___:___LETSENCRYPT_PORT___;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443;
|
||||
server_name ___my.example.com___ www.___my.example.com___;
|
||||
|
||||
ssl on;
|
||||
ssl_certificate /etc/letsencrypt/live/___my.example.com___/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/___my.example.com___/privkey.pem;
|
||||
ssl_session_timeout 5m;
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_dhparam /etc/ssl/private/dhparams.pem;
|
||||
|
||||
location /.well-known/acme-challenge {
|
||||
proxy_pass http://___LETSENCRYPT_HTTPS_IP___:___LETSENCRYPT_HTTPS_PORT___;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
}
|
||||
|
||||
location / {
|
||||
# checks for static file, if not found proxy to app
|
||||
try_files $uri @proxy_to_app;
|
||||
}
|
||||
|
||||
# cookiecutter-django app
|
||||
location @proxy_to_app {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_redirect off;
|
||||
|
||||
proxy_pass http://app;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -9,9 +9,9 @@ events {
|
|||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
|
@ -31,23 +31,40 @@ http {
|
|||
server django:5000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
charset utf-8;
|
||||
server {
|
||||
listen 80;
|
||||
charset utf-8;
|
||||
|
||||
{% if cookiecutter.use_lets_encrypt == 'y' and cookiecutter.use_docker == 'y' %}
|
||||
server_name ___my.example.com___ ;
|
||||
|
||||
location / {
|
||||
location /.well-known/acme-challenge {
|
||||
proxy_pass http://___LETSENCRYPT_IP___:___LETSENCRYPT_PORT___;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
|
||||
location / {
|
||||
# checks for static file, if not found proxy to app
|
||||
try_files $uri @proxy_to_app;
|
||||
}
|
||||
|
||||
location @proxy_to_app {
|
||||
|
||||
# cookiecutter-django app
|
||||
location @proxy_to_app {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_redirect off;
|
||||
|
||||
proxy_pass http://app;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
81
{{cookiecutter.project_slug}}/compose/nginx/start.sh
Executable file
81
{{cookiecutter.project_slug}}/compose/nginx/start.sh
Executable file
|
@ -0,0 +1,81 @@
|
|||
echo sleep 5
|
||||
sleep 5
|
||||
|
||||
echo build starting nginx config
|
||||
|
||||
|
||||
echo replacing ___my.example.com___/$MY_DOMAIN_NAME
|
||||
echo replacing ___LETSENCRYPT_IP___/$LETSENCRYPT_PORT_80_TCP_ADDR
|
||||
echo replacing ___LETSENCRYPT_PORT___/$LETSENCRYPT_PORT_80_TCP_PORT
|
||||
echo replacing ___APPLICATION_IP___/$APP_PORT_80_TCP_ADDR
|
||||
echo replacing ___APPLICATION_PORT___/$APP_PORT_80_TCP_PORT
|
||||
|
||||
# Put your domain name into the nginx reverse proxy config.
|
||||
sed -i "s/___my.example.com___/$MY_DOMAIN_NAME/g" /etc/nginx/nginx.conf
|
||||
# Add your app's container IP and port into config
|
||||
sed -i "s/___APPLICATION_IP___/$APP_PORT_80_TCP_ADDR/g" /etc/nginx/nginx.conf
|
||||
sed -i "s/___APPLICATION_PORT___/$APP_PORT_80_TCP_PORT/g" /etc/nginx/nginx.conf
|
||||
sed -i "s/___LETSENCRYPT_IP___/$LETSENCRYPT_PORT_80_TCP_ADDR/g" /etc/nginx/nginx.conf
|
||||
sed -i "s/___LETSENCRYPT_PORT___/$LETSENCRYPT_PORT_80_TCP_PORT/g" /etc/nginx/nginx.conf
|
||||
|
||||
cat /etc/nginx/nginx.conf
|
||||
echo .
|
||||
echo Firing up nginx in the background.
|
||||
nginx
|
||||
|
||||
# # Check user has specified domain name
|
||||
if [ -z "$MY_DOMAIN_NAME" ]; then
|
||||
echo "Need to set MY_DOMAIN_NAME (to a letsencrypt-registered name)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# This bit waits until the letsencrypt container has done its thing.
|
||||
# We see the changes here bceause there's a docker volume mapped.
|
||||
echo Waiting for folder /etc/letsencrypt/live/$MY_DOMAIN_NAME to exist
|
||||
while [ ! -d /etc/letsencrypt/live/$MY_DOMAIN_NAME ] ;
|
||||
do
|
||||
sleep 2
|
||||
done
|
||||
|
||||
while [ ! -f /etc/letsencrypt/live/$MY_DOMAIN_NAME/fullchain.pem ] ;
|
||||
do
|
||||
echo Waiting for file fullchain.pem to exist
|
||||
sleep 2
|
||||
done
|
||||
|
||||
while [ ! -f /etc/letsencrypt/live/$MY_DOMAIN_NAME/privkey.pem ] ;
|
||||
do
|
||||
echo Waiting for file privkey.pem to exist
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# This is added so that when the certificate is being renewed or is already in place, nginx waits for everything to be good.
|
||||
sleep 15
|
||||
|
||||
echo replacing ___my.example.com___/$MY_DOMAIN_NAME
|
||||
echo replacing ___LETSENCRYPT_IP___/$LETSENCRYPT_PORT_80_TCP_ADDR
|
||||
echo replacing ___LETSENCRYPT_PORT___/$LETSENCRYPT_PORT_80_TCP_PORT
|
||||
echo replacing ___LETSENCRYPT_HTTPS_IP___/$LETSENCRYPT_PORT_443_TCP_ADDR
|
||||
echo replacing ___LETSENCRYPT_HTTPS_PORT___/$LETSENCRYPT_PORT_443_TCP_PORT
|
||||
echo replacing ___APPLICATION_IP___/$APP_PORT_80_TCP_ADDR
|
||||
echo replacing ___APPLICATION_PORT___/$APP_PORT_80_TCP_PORT
|
||||
|
||||
|
||||
# Put your domain name into the nginx reverse proxy config.
|
||||
sed -i "s/___my.example.com___/$MY_DOMAIN_NAME/g" /etc/nginx/nginx-secure.conf
|
||||
|
||||
# Add LE container IP and port into config
|
||||
sed -i "s/___LETSENCRYPT_IP___/$LETSENCRYPT_PORT_80_TCP_ADDR/g" /etc/nginx/nginx-secure.conf
|
||||
sed -i "s/___LETSENCRYPT_PORT___/$LETSENCRYPT_PORT_80_TCP_PORT/g" /etc/nginx/nginx-secure.conf
|
||||
sed -i "s/___LETSENCRYPT_HTTPS_IP___/$LETSENCRYPT_PORT_443_TCP_ADDR/g" /etc/nginx/nginx-secure.conf
|
||||
sed -i "s/___LETSENCRYPT_HTTPS_PORT___/$LETSENCRYPT_PORT_443_TCP_PORT/g" /etc/nginx/nginx-secure.conf
|
||||
|
||||
# Add your app's container IP and port into config
|
||||
sed -i "s/___APPLICATION_IP___/$APP_PORT_80_TCP_ADDR/g" /etc/nginx/nginx-secure.conf
|
||||
sed -i "s/___APPLICATION_PORT___/$APP_PORT_80_TCP_PORT/g" /etc/nginx/nginx-secure.conf
|
||||
|
||||
#go!
|
||||
kill $(ps aux | grep 'nginx' | awk '{print $2}')
|
||||
cp /etc/nginx/nginx-secure.conf /etc/nginx/nginx.conf
|
||||
|
||||
nginx -g 'daemon off;'
|
|
@ -53,7 +53,7 @@ INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
|
|||
# MIDDLEWARE CONFIGURATION
|
||||
# ------------------------------------------------------------------------------
|
||||
MIDDLEWARE_CLASSES = (
|
||||
# Make sure djangosecure.middleware.SecurityMiddleware is listed first
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
|
|
|
@ -6,7 +6,7 @@ Production Configurations
|
|||
- Use Amazon's S3 for storing static files and uploaded media
|
||||
- Use mailgun to send emails
|
||||
- Use Redis on Heroku
|
||||
{% if cookiecutter.use_sentry == 'y' %}
|
||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
||||
- Use sentry for error logging
|
||||
{% endif %}
|
||||
{% if cookiecutter.use_opbeat == 'y' %}
|
||||
|
@ -17,7 +17,7 @@ from __future__ import absolute_import, unicode_literals
|
|||
|
||||
from boto.s3.connection import OrdinaryCallingFormat
|
||||
from django.utils import six
|
||||
{% if cookiecutter.use_sentry == 'y' %}
|
||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
||||
import logging
|
||||
{% endif %}
|
||||
|
||||
|
@ -29,40 +29,27 @@ from .common import * # noqa
|
|||
# Raises ImproperlyConfigured exception if DJANGO_SECRET_KEY not in os.environ
|
||||
SECRET_KEY = env('DJANGO_SECRET_KEY')
|
||||
|
||||
|
||||
# This ensures that Django will be able to detect a secure connection
|
||||
# properly on Heroku.
|
||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||
|
||||
# django-secure
|
||||
# ------------------------------------------------------------------------------
|
||||
INSTALLED_APPS += ('djangosecure', )
|
||||
{% if cookiecutter.use_sentry == 'y' -%}
|
||||
{%- if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
||||
# raven sentry client
|
||||
# See https://docs.getsentry.com/hosted/clients/python/integrations/django/
|
||||
INSTALLED_APPS += ('raven.contrib.django.raven_compat', )
|
||||
{%- endif %}
|
||||
SECURITY_MIDDLEWARE = (
|
||||
'djangosecure.middleware.SecurityMiddleware',
|
||||
)
|
||||
{% if cookiecutter.use_whitenoise == 'y' -%}
|
||||
{% endif %}
|
||||
{%- if cookiecutter.use_whitenoise == 'y' %}
|
||||
# Use Whitenoise to serve static files
|
||||
# See: https://whitenoise.readthedocs.io/
|
||||
WHITENOISE_MIDDLEWARE = (
|
||||
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||
)
|
||||
WHITENOISE_MIDDLEWARE = ('whitenoise.middleware.WhiteNoiseMiddleware', )
|
||||
MIDDLEWARE_CLASSES = WHITENOISE_MIDDLEWARE + MIDDLEWARE_CLASSES
|
||||
{%- endif %}
|
||||
{% if cookiecutter.use_sentry == 'y' -%}
|
||||
RAVEN_MIDDLEWARE = (
|
||||
'raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware',
|
||||
)
|
||||
{% endif %}
|
||||
{%- if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
||||
RAVEN_MIDDLEWARE = ('raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware', )
|
||||
MIDDLEWARE_CLASSES = RAVEN_MIDDLEWARE + MIDDLEWARE_CLASSES
|
||||
{%- endif %}
|
||||
|
||||
# Make sure djangosecure.middleware.SecurityMiddleware is listed first
|
||||
MIDDLEWARE_CLASSES = SECURITY_MIDDLEWARE + MIDDLEWARE_CLASSES
|
||||
|
||||
{% if cookiecutter.use_opbeat == 'y' -%}
|
||||
{% endif %}
|
||||
{%- if cookiecutter.use_opbeat == 'y' -%}
|
||||
# opbeat integration
|
||||
# See https://opbeat.com/languages/django/
|
||||
INSTALLED_APPS += ('opbeat.contrib.django',)
|
||||
|
@ -74,7 +61,13 @@ OPBEAT = {
|
|||
MIDDLEWARE_CLASSES = (
|
||||
'opbeat.contrib.django.middleware.OpbeatAPMMiddleware',
|
||||
) + MIDDLEWARE_CLASSES
|
||||
{%- endif %}
|
||||
{% endif %}
|
||||
|
||||
# SECURITY CONFIGURATION
|
||||
# ------------------------------------------------------------------------------
|
||||
# See https://docs.djangoproject.com/en/1.9/ref/middleware/#module-django.middleware.security
|
||||
# and https://docs.djangoproject.com/ja/1.9/howto/deployment/checklist/#run-manage-py-check-deploy
|
||||
|
||||
# set this to 60 seconds and then to 518400 when you can prove it works
|
||||
SECURE_HSTS_SECONDS = 60
|
||||
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool(
|
||||
|
@ -82,9 +75,12 @@ SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool(
|
|||
SECURE_CONTENT_TYPE_NOSNIFF = env.bool(
|
||||
'DJANGO_SECURE_CONTENT_TYPE_NOSNIFF', default=True)
|
||||
SECURE_BROWSER_XSS_FILTER = True
|
||||
SESSION_COOKIE_SECURE = False
|
||||
SESSION_COOKIE_SECURE = True
|
||||
SESSION_COOKIE_HTTPONLY = True
|
||||
SECURE_SSL_REDIRECT = env.bool('DJANGO_SECURE_SSL_REDIRECT', default=True)
|
||||
CSRF_COOKIE_SECURE = True
|
||||
CSRF_COOKIE_HTTPONLY = True
|
||||
X_FRAME_OPTIONS = 'DENY'
|
||||
|
||||
# SITE CONFIGURATION
|
||||
# ------------------------------------------------------------------------------
|
||||
|
@ -95,6 +91,7 @@ ALLOWED_HOSTS = env.list('DJANGO_ALLOWED_HOSTS', default=['{{cookiecutter.domain
|
|||
|
||||
INSTALLED_APPS += ('gunicorn', )
|
||||
|
||||
|
||||
# STORAGE CONFIGURATION
|
||||
# ------------------------------------------------------------------------------
|
||||
# Uploaded Media Files
|
||||
|
@ -165,11 +162,6 @@ ANYMAIL = {
|
|||
}
|
||||
EMAIL_BACKEND = "anymail.backends.mailgun.MailgunBackend"
|
||||
|
||||
{% if cookiecutter.use_newrelic == 'y'-%}# NEW RELIC
|
||||
# ------------------------------------------------------------------------------
|
||||
NEW_RELIC_LICENSE_KEY = env('NEW_RELIC_LICENSE_KEY')
|
||||
NEW_RELIC_APP_NAME = env('NEW_RELIC_APP_NAME')
|
||||
{%- endif %}
|
||||
# TEMPLATE CONFIGURATION
|
||||
# ------------------------------------------------------------------------------
|
||||
# See:
|
||||
|
@ -199,7 +191,7 @@ CACHES = {
|
|||
}
|
||||
}
|
||||
|
||||
{% if cookiecutter.use_sentry == 'y' %}
|
||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' %}
|
||||
# Sentry Configuration
|
||||
SENTRY_DSN = env('DJANGO_SENTRY_DSN')
|
||||
SENTRY_CLIENT = env('DJANGO_SENTRY_CLIENT', default='raven.contrib.django.raven_compat.DjangoClient')
|
||||
|
@ -255,7 +247,7 @@ RAVEN_CONFIG = {
|
|||
'CELERY_LOGLEVEL': env.int('DJANGO_SENTRY_LOG_LEVEL', logging.INFO),
|
||||
'DSN': SENTRY_DSN
|
||||
}
|
||||
{% elif cookiecutter.use_sentry == 'n' %}
|
||||
{% elif cookiecutter.use_sentry_for_error_reporting == 'n' %}
|
||||
# LOGGING CONFIGURATION
|
||||
# ------------------------------------------------------------------------------
|
||||
# See: https://docs.djangoproject.com/en/dev/ref/settings/#logging
|
||||
|
|
|
@ -15,13 +15,8 @@ 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_sentry == 'y' -%}
|
||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
||||
if os.environ.get('DJANGO_SETTINGS_MODULE') == 'config.settings.production':
|
||||
from raven.contrib.django.raven_compat.middleware.wsgi import Sentry
|
||||
{%- endif %}
|
||||
|
@ -36,14 +31,10 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
|
|||
# file. This includes Django's development server, if the WSGI_APPLICATION
|
||||
# setting points here.
|
||||
application = get_wsgi_application()
|
||||
{% if cookiecutter.use_sentry == 'y' -%}
|
||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
||||
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)
|
||||
|
|
|
@ -27,12 +27,38 @@ services:
|
|||
build: ./compose/nginx
|
||||
depends_on:
|
||||
- django
|
||||
{% if cookiecutter.use_lets_encrypt == 'y' %}
|
||||
- certbot
|
||||
{% endif %}
|
||||
ports:
|
||||
- "0.0.0.0:80:80"
|
||||
{% if cookiecutter.use_lets_encrypt == 'y' %}
|
||||
environment:
|
||||
- MY_DOMAIN_NAME={{ cookiecutter.domain_name }}
|
||||
ports:
|
||||
- "0.0.0.0:80:80"
|
||||
- "0.0.0.0:443:443"
|
||||
volumes:
|
||||
- /etc/letsencrypt:/etc/letsencrypt
|
||||
- /var/lib/letsencrypt:/var/lib/letsencrypt
|
||||
|
||||
certbot:
|
||||
image: quay.io/letsencrypt/letsencrypt
|
||||
command: bash -c "sleep 6 && certbot certonly -n --standalone -d {{ cookiecutter.domain_name }} --text --agree-tos --email {{ cookiecutter.email }} --server https://acme-v01.api.letsencrypt.org/directory --rsa-key-size 4096 --verbose --keep-until-expiring --standalone-supported-challenges http-01"
|
||||
entrypoint: ""
|
||||
volumes:
|
||||
- /etc/letsencrypt:/etc/letsencrypt
|
||||
- /var/lib/letsencrypt:/var/lib/letsencrypt
|
||||
ports:
|
||||
- "80"
|
||||
- "443"
|
||||
environment:
|
||||
- TERM=xterm
|
||||
{% endif %}
|
||||
|
||||
redis:
|
||||
image: redis:3.0
|
||||
{% if cookiecutter.use_celery == 'y' %}
|
||||
{% if cookiecutter.use_celery == 'y' %}
|
||||
celeryworker:
|
||||
build:
|
||||
context: .
|
||||
|
@ -54,4 +80,4 @@ services:
|
|||
- postgres
|
||||
- redis
|
||||
command: celery -A {{cookiecutter.project_slug}}.taskapp beat -l INFO
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
|
|
@ -44,7 +44,7 @@ master_doc = 'index'
|
|||
|
||||
# General information about the project.
|
||||
project = '{{ cookiecutter.project_name }}'
|
||||
copyright = """{{ cookiecutter.year }}, {{ cookiecutter.author_name }}"""
|
||||
copyright = """{% now 'utc', '%Y' %}, {{ cookiecutter.author_name }}"""
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
|
|
|
@ -12,13 +12,9 @@ DJANGO_MAILGUN_API_KEY=
|
|||
DJANGO_SERVER_EMAIL=
|
||||
DJANGO_SECURE_SSL_REDIRECT=False
|
||||
DJANGO_ACCOUNT_ALLOW_REGISTRATION=True
|
||||
{% if cookiecutter.use_sentry == 'y' -%}
|
||||
{% if cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
||||
DJANGO_SENTRY_DSN=
|
||||
{% endif %}
|
||||
{% if cookiecutter.use_newrelic == 'y' -%}
|
||||
NEW_RELIC_LICENSE_KEY=
|
||||
NEW_RELIC_APP_NAME={{cookiecutter.project_slug}}
|
||||
{% endif %}
|
||||
{% if cookiecutter.use_opbeat == 'y' -%}
|
||||
DJANGO_OPBEAT_ORGANIZATION_ID
|
||||
DJANGO_OPBEAT_APP_ID
|
||||
|
|
107
{{cookiecutter.project_slug}}/gulpfile.js
Normal file
107
{{cookiecutter.project_slug}}/gulpfile.js
Normal file
|
@ -0,0 +1,107 @@
|
|||
|
||||
////////////////////////////////
|
||||
//Setup//
|
||||
////////////////////////////////
|
||||
|
||||
// Plugins
|
||||
var gulp = require('gulp'),
|
||||
pjson = require('./package.json'),
|
||||
gutil = require('gulp-util'),
|
||||
sass = require('gulp-sass'),
|
||||
autoprefixer = require('gulp-autoprefixer'),
|
||||
cssnano = require('gulp-cssnano'),
|
||||
rename = require('gulp-rename'),
|
||||
del = require('del'),
|
||||
plumber = require('gulp-plumber'),
|
||||
pixrem = require('gulp-pixrem'),
|
||||
uglify = require('gulp-uglify'),
|
||||
imagemin = require('gulp-imagemin'),
|
||||
exec = require('gulp-exec'),
|
||||
runSequence = require('run-sequence'),
|
||||
browserSync = require('browser-sync');
|
||||
|
||||
|
||||
// Relative paths function
|
||||
var pathsConfig = function (appName) {
|
||||
this.app = "./" + (appName || pjson.name);
|
||||
|
||||
return {
|
||||
app: this.app,
|
||||
templates: this.app + '/templates',
|
||||
css: this.app + '/static/css',
|
||||
sass: this.app + '/static/sass',
|
||||
fonts: this.app + '/static/fonts',
|
||||
images: this.app + '/static/images',
|
||||
js: this.app + '/static/js',
|
||||
}
|
||||
};
|
||||
|
||||
var paths = pathsConfig();
|
||||
|
||||
////////////////////////////////
|
||||
//Tasks//
|
||||
////////////////////////////////
|
||||
|
||||
// Styles autoprefixing and minification
|
||||
gulp.task('styles', function() {
|
||||
return gulp.src(paths.sass + '/project.scss')
|
||||
.pipe(sass().on('error', sass.logError))
|
||||
.pipe(plumber()) // Checks for errors
|
||||
.pipe(autoprefixer({browsers: ['last 2 version']})) // Adds vendor prefixes
|
||||
.pipe(pixrem()) // add fallbacks for rem units
|
||||
.pipe(gulp.dest(paths.css))
|
||||
.pipe(rename({ suffix: '.min' }))
|
||||
.pipe(cssnano()) // Minifies the result
|
||||
.pipe(gulp.dest(paths.css));
|
||||
});
|
||||
|
||||
// Javascript minification
|
||||
gulp.task('scripts', function() {
|
||||
return gulp.src(paths.js + '/project.js')
|
||||
.pipe(plumber()) // Checks for errors
|
||||
.pipe(uglify()) // Minifies the js
|
||||
.pipe(rename({ suffix: '.min' }))
|
||||
.pipe(gulp.dest(paths.js));
|
||||
});
|
||||
|
||||
// Image compression
|
||||
gulp.task('imgCompression', function(){
|
||||
return gulp.src(paths.images + '/*')
|
||||
.pipe(imagemin()) // Compresses PNG, JPEG, GIF and SVG images
|
||||
.pipe(gulp.dest(paths.images))
|
||||
});
|
||||
|
||||
// Run django server
|
||||
gulp.task('runServer', function() {
|
||||
exec('python manage.py runserver', function (err, stdout, stderr) {
|
||||
console.log(stdout);
|
||||
console.log(stderr);
|
||||
});
|
||||
});
|
||||
|
||||
// Browser sync server for live reload
|
||||
gulp.task('browserSync', function() {
|
||||
browserSync.init(
|
||||
[paths.css + "/*.css", paths.js + "*.js", paths.templates + '*.html'], {
|
||||
proxy: "localhost:8000"
|
||||
});
|
||||
});
|
||||
|
||||
// Default task
|
||||
gulp.task('default', function() {
|
||||
runSequence(['styles', 'scripts', 'imgCompression'], 'runServer', 'browserSync');
|
||||
});
|
||||
|
||||
////////////////////////////////
|
||||
//Watch//
|
||||
////////////////////////////////
|
||||
|
||||
// Watch
|
||||
gulp.task('watch', ['default'], function() {
|
||||
|
||||
gulp.watch(paths.sass + '/*.scss', ['styles']);
|
||||
gulp.watch(paths.js + '/*.js', ['scripts']);
|
||||
gulp.watch(paths.images + '/*', ['imgCompression']);
|
||||
gulp.watch('templates/*.html');
|
||||
|
||||
});
|
|
@ -3,17 +3,34 @@
|
|||
"version": "{{ cookiecutter.version }}",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.5",
|
||||
"grunt-contrib-watch": "~0.6.1",
|
||||
"grunt-bg-shell": "~2.3.1",
|
||||
"connect-livereload": "~0.3.2",
|
||||
"time-grunt": "~1.2.1",
|
||||
"load-grunt-tasks": "~3.2.0",
|
||||
"grunt-sass": "~1.0.0",
|
||||
"grunt-postcss": "~0.5.5",
|
||||
"cssnano": "~2.1.0",
|
||||
{% if cookiecutter.js_task_runner == 'Grunt' %}
|
||||
"autoprefixer-core": "~5.2.1",
|
||||
"pixrem": "~1.3.1"
|
||||
"connect-livereload": "~0.3.2",
|
||||
"cssnano": "~2.1.0",
|
||||
"grunt": "~0.4.5",
|
||||
"grunt-bg-shell": "~2.3.1",
|
||||
"grunt-contrib-watch": "~0.6.1",
|
||||
"grunt-postcss": "~0.5.5",
|
||||
"grunt-sass": "~1.0.0",
|
||||
"load-grunt-tasks": "~3.2.0",
|
||||
"pixrem": "~1.3.1",
|
||||
"time-grunt": "~1.2.1"
|
||||
{% elif cookiecutter.js_task_runner == 'Gulp' %}
|
||||
"browser-sync": "^2.12.10",
|
||||
"del": "^2.2.0",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-autoprefixer": "^3.1.0",
|
||||
"gulp-cssnano": "^2.1.2",
|
||||
"gulp-exec": "^2.1.2",
|
||||
"gulp-imagemin": "^3.0.1",
|
||||
"gulp-pixrem": "^1.0.0",
|
||||
"gulp-plumber": "^1.1.0",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-sass": "^2.3.1",
|
||||
"gulp-uglify": "^1.5.3",
|
||||
"gulp-util": "^3.0.7",
|
||||
"run-sequence": "^1.2.1"
|
||||
{% endif %}
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
|
|
|
@ -7,18 +7,17 @@ wheel==0.29.0
|
|||
{%- endif %}
|
||||
|
||||
# Bleeding edge Django
|
||||
django==1.9.6
|
||||
django==1.9.7
|
||||
|
||||
# Configuration
|
||||
django-environ==0.4.0
|
||||
django-secure==1.0.1
|
||||
{% if cookiecutter.use_whitenoise == 'y' -%}
|
||||
whitenoise==3.0
|
||||
whitenoise==3.2
|
||||
{%- endif %}
|
||||
|
||||
|
||||
# Forms
|
||||
django-braces==1.8.1
|
||||
django-braces==1.9.0
|
||||
django-crispy-forms==1.6.0
|
||||
django-floppyforms==1.6.2
|
||||
|
||||
|
@ -48,7 +47,7 @@ django-autoslug==1.9.3
|
|||
pytz==2016.4
|
||||
|
||||
# Redis support
|
||||
django-redis==4.4.2
|
||||
django-redis==4.4.3
|
||||
redis>=2.10.0
|
||||
|
||||
{% if cookiecutter.use_celery == "y" %}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# Local development dependencies go here
|
||||
-r base.txt
|
||||
coverage==4.0.3
|
||||
django_coverage_plugin==1.3
|
||||
coverage==4.1
|
||||
django-coverage-plugin==1.3.1
|
||||
Sphinx
|
||||
django-extensions==1.6.7
|
||||
Werkzeug==0.11.9
|
||||
django-test-plus==1.0.12
|
||||
Werkzeug==0.11.10
|
||||
django-test-plus==1.0.13
|
||||
factory_boy==2.7.0
|
||||
django-debug-toolbar==1.4
|
||||
|
||||
|
@ -17,4 +17,4 @@ pytest-sugar==0.7.1
|
|||
|
||||
{% if cookiecutter.use_precommit_hooks == 'y' -%}
|
||||
pre-commit==0.8.2
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
|
|
|
@ -12,7 +12,7 @@ psycopg2==2.6.1
|
|||
# WSGI Handler
|
||||
# ------------------------------------------------
|
||||
gevent==1.1.1
|
||||
gunicorn==19.5.0
|
||||
gunicorn==19.6.0
|
||||
|
||||
# Static and Media Storage
|
||||
# ------------------------------------------------
|
||||
|
@ -26,18 +26,12 @@ Collectfast==0.2.3
|
|||
# -------------------------------------------------------
|
||||
django-anymail==0.3.1
|
||||
|
||||
{% if cookiecutter.use_sentry == "y" -%}
|
||||
{% if cookiecutter.use_sentry_for_error_reporting == "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
|
||||
# -----------------------------------------
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
psycopg2==2.6.1
|
||||
{%- endif %}
|
||||
|
||||
coverage==4.0.3
|
||||
django_coverage_plugin==1.3
|
||||
coverage==4.1
|
||||
django-coverage-plugin==1.3.1
|
||||
flake8==2.5.4
|
||||
django-test-plus==1.0.12
|
||||
django-test-plus==1.0.13
|
||||
factory_boy==2.7.0
|
||||
|
||||
# pytest
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
|
||||
// project specific CSS goes here
|
||||
|
||||
////////////////////////////////
|
||||
//Variables//
|
||||
////////////////////////////////
|
||||
|
||||
// Alert colors
|
||||
|
||||
$white: #fff;
|
||||
|
@ -9,6 +14,10 @@ $pink: #f2dede;
|
|||
$dark-pink: #eed3d7;
|
||||
$red: #b94a48;
|
||||
|
||||
////////////////////////////////
|
||||
//Alerts//
|
||||
////////////////////////////////
|
||||
|
||||
// bootstrap alert CSS, translated to the django-standard levels of
|
||||
// debug, info, success, warning, error
|
||||
|
||||
|
@ -24,8 +33,16 @@ $red: #b94a48;
|
|||
color: $red;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//Navbar//
|
||||
////////////////////////////////
|
||||
|
||||
// This is a fix for the bootstrap4 alpha release
|
||||
|
||||
.navbar {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
@media (max-width: 47.9em) {
|
||||
.navbar-nav .nav-item {
|
||||
display: inline-block;
|
||||
|
@ -42,6 +59,10 @@ $red: #b94a48;
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//Django Toolbar//
|
||||
////////////////////////////////
|
||||
|
||||
// Display django-debug-toolbar.
|
||||
// See https://github.com/django-debug-toolbar/django-debug-toolbar/issues/742
|
||||
// and https://github.com/pydanny/cookiecutter-django/issues/317
|
||||
|
|
|
@ -24,7 +24,7 @@ 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 cookiecutter.use_sentry_for_error_reporting == 'y' -%}
|
||||
if hasattr(settings, 'RAVEN_CONFIG'):
|
||||
# Celery signal registration
|
||||
from raven import Client as RavenClient
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% raw %}{% load staticfiles i18n %}<!DOCTYPE html>
|
||||
<html lang="en" {% endraw %}{% if cookiecutter.use_angular == "y" %}ng-app{% endif %}{% raw %}>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
|
@ -15,7 +15,7 @@
|
|||
|
||||
{% block css %}
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link rel="stylesheet" href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" integrity="sha384-y3tfxAZXuh4HwSYylfB+J125MxIs6mR5FOHamPBG064zB+AFeWH94NdvaCBm8qnd" crossorigin="anonymous">
|
||||
|
||||
<!-- Your stuff: Third-party css libraries go here -->
|
||||
|
||||
|
@ -23,10 +23,6 @@
|
|||
<link href="{% static 'css/project.css' %}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
|
||||
{% endraw %}{% if cookiecutter.use_angular == "y" %}{% raw %}{% block angular %}
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
|
||||
{% endblock %}{% endraw %}{% endif %}{% raw %}
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -99,7 +95,7 @@
|
|||
<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://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.js"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/js/bootstrap.min.js" integrity="sha384-vZ2WRJMwsjRMW/8U7i6PWi6AlO1L79snBrmgiDpgIWJ82z8eA5lenwvxbMV1PAh7" crossorigin="anonymous"></script>
|
||||
|
||||
<!-- Your stuff: Third-party javascript libraries go here -->
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ from django import forms
|
|||
from django.contrib import admin
|
||||
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
|
||||
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
|
||||
|
||||
from .models import User
|
||||
|
||||
|
||||
|
@ -24,7 +23,7 @@ class MyUserCreationForm(UserCreationForm):
|
|||
model = User
|
||||
|
||||
def clean_username(self):
|
||||
username = self.cleaned_data['username']
|
||||
username = self.cleaned_data["username"]
|
||||
try:
|
||||
User.objects.get(username=username)
|
||||
except User.DoesNotExist:
|
||||
|
@ -33,6 +32,11 @@ class MyUserCreationForm(UserCreationForm):
|
|||
|
||||
|
||||
@admin.register(User)
|
||||
class UserAdmin(AuthUserAdmin):
|
||||
class MyUserAdmin(AuthUserAdmin):
|
||||
form = MyUserChangeForm
|
||||
add_form = MyUserCreationForm
|
||||
fieldsets = (
|
||||
('User Profile', {'fields': ('name',)}),
|
||||
) + AuthUserAdmin.fieldsets
|
||||
list_display = ('username', 'name', 'is_superuser')
|
||||
search_fields = ['name']
|
||||
|
|
Loading…
Reference in New Issue
Block a user