This commit is contained in:
Jannis Gebauer 2015-10-24 18:46:49 +02:00
commit 1f36ed3c8e
18 changed files with 229 additions and 121 deletions

View File

@ -2,6 +2,48 @@
All enhancements and patches to cookiecutter-django will be documented in this file. All enhancements and patches to cookiecutter-django will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/). This project adheres to [Semantic Versioning](http://semver.org/).
## [2015-10-22]
### Removed
- Remove unnecessary .gitkeep in static/images/ (@audreyr)
## [2015-10-21]
### Changed
- TODO (@pydanny)
- TODO (@theskumar)
## [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] ## [2015-09-30]
### Changed ### Changed
- Fixed Sentry logging with celery (@jayfk) - Fixed Sentry logging with celery (@jayfk)

View File

@ -56,6 +56,9 @@ Code Contributors
* @kaidokert * @kaidokert
* Raphael Pierzina / @hackebrot * Raphael Pierzina / @hackebrot
* Alvaro [Andor] / @andor-pierdelacabeza * Alvaro [Andor] / @andor-pierdelacabeza
* Chris Franklin / @hairychris
* Anna Callahan / @jazztpt
* Mathijs Hoogland / @MathijsHoogland
\* Possesses commit rights \* Possesses commit rights

View File

@ -4,29 +4,28 @@ Getting Up and Running with Docker
.. index:: Docker .. index:: Docker
The steps below will get you up and running with a local development environment. 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 Prerequisites
-------------- --------------
If you don't already have these installed, get them all by installing `Docker Toolbox`_.
* docker * docker
* docker-machine * docker-machine
* docker-compose * docker-compose
* virtualbox * virtualbox
If you don't already have these installed, you can get them at: .. _`Docker Toolbox`: https://github.com/docker/toolbox/releases
* https://github.com/docker/toolbox/releases Create the Machine (Optional)
* https://www.virtualbox.org/wiki/Downloads -------------------------------
Go to the Root of your Project On Ubuntu you have native Docker, so you don't need to create a VM with
------------------------------ docker-machine to use it.
All of these commands assume you are in the root of your generated project. However, on Mac/Windows/other systems without native Docker, you'll want to
start by creating a VM with docker-machine::
Create the Machine
-------------------
::
$ docker-machine create --driver virtualbox dev1 $ docker-machine create --driver virtualbox dev1
@ -34,29 +33,16 @@ Create the Machine
name them accordingly. Instead of 'dev1' you might have 'dev2', 'myproject', name them accordingly. Instead of 'dev1' you might have 'dev2', 'myproject',
'djangopackages', et al. 'djangopackages', et al.
Make the new machine the active unit
-------------------------------------
This tells our computer that all future commands are specifically for the just
created machine. Using the ``eval`` command we can switch machines as needed.
::
$ eval "$(docker-machine env dev1)"
Get the IP Address Get the IP Address
-------------------- --------------------
Acquiring the IP Address is good for two reasons: Once your machine is up and running, run this::
1. Confirms that the machine is up and running.
2. Tells us the IP address where our Django project is being served.
::
$ docker-machine ip dev1 $ docker-machine ip dev1
123.456.789.012 123.456.789.012
This is also the IP address where the Django project will be served from.
Saving changes Saving changes
-------------- --------------
@ -64,15 +50,12 @@ If you are using OS X or Windows, you need to create a /data partition inside th
virtual machine that runs the docker deamon in order make all changes persistent. virtual machine that runs the docker deamon in order make all changes persistent.
If you don't do that your /data directory will get wiped out on every reboot. If you don't do that your /data directory will get wiped out on every reboot.
To create a persistent folder, log into the virtual machine by running: To create a persistent folder, log into the virtual machine by running::
::
$ docker-machine ssh dev1 $ docker-machine ssh dev1
$ sudo su $ sudo su
$ echo 'ln -sfn /mnt/sda1/data /data' >> /var/lib/boot2docker/bootlocal.sh $ 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 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 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 host volumes if the container creates his own user and chown's the directories
@ -83,57 +66,19 @@ Build the Stack
--------------- ---------------
This can take a while, especially the first time you run this particular command This can take a while, especially the first time you run this particular command
on your development system. on your development system::
:: $ docker-compose -f dev.yml build
$ docker-compose 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 Boot the System
------------------------------ ---------------
This brings up both Django and PostgreSQL. The first time it is run it might This brings up both Django and PostgreSQL.
take a while to get started, but subsequent runs will occur quickly.
:: The first time it is run it might take a while to get started, but subsequent
runs will occur quickly.
$ docker-compose -f dev.yml up
If you want to run the entire system in production mode, then run:
::
$ docker-compose up
If you want to run the stack in detached mode (in the background), use the ``-d`` argument::
::
$ docker-compose up -d
Running bash commands (i.e. management commands)
----------------------------------------------------
This is done using the ``docker-compose run`` command. In the following examples
we specify the ``django`` container as the location to run our management commands.
Example:
$ docker-compose run django python manage.py migrate
$ docker-compose run django python manage.py createsuperuser
Deprecated
==========
**Note:** This segment of documentation is being kept in this location as part of our documentation transition process.
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:: Open a terminal at the project root and run the following for local development::
@ -147,9 +92,42 @@ And then run::
$ docker-compose up $ 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:: 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 migrate
$ docker-compose run django python manage.py createsuperuser $ docker-compose 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`.
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 up -d

View File

@ -15,11 +15,9 @@ First make sure to create and activate a virtualenv_, then open a terminal at th
.. _virtualenv: http://docs.python-guide.org/en/latest/dev/virtualenvs/ .. _virtualenv: http://docs.python-guide.org/en/latest/dev/virtualenvs/
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: Then, create a PostgreSQL database with the following command, where `[repo_name]` is what value you entered for your project's `repo_name`::
* in the ``config.settings.common.py`` setting file,
* or in the environment variable ``DATABASE_URL``
$ createdb [repo_name]
You can now run the usual Django ``migrate`` and ``runserver`` command:: You can now run the usual Django ``migrate`` and ``runserver`` command::

View File

@ -15,6 +15,7 @@ Contents:
:maxdepth: 2 :maxdepth: 2
project-generation-options
developing-locally developing-locally
developing-locally-docker developing-locally-docker
settings settings

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_maildump [n]
Whether to use Maildump_. Maildump is a tool that simulates email receiving
for development purposes. It runs a super simple SMTP server which catches
any message sent to it. Then messages are displayed in a web interface.
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
.. _Maildump: https://github.com/ThiefMaster/maildump
.. _Sentry: https://github.com/getsentry/sentry

View File

@ -55,28 +55,43 @@ def get_random_string(
).digest()) ).digest())
return ''.join(random.choice(allowed_chars) for i in range(length)) return ''.join(random.choice(allowed_chars) for i in range(length))
def make_secret_key(project_directory): def set_secret_key(setting_file_location):
"""Generates and saves random secret key"""
# Determine the local_setting_file_location
local_setting_file_location = os.path.join(
project_directory,
'config/settings/local.py'
)
# Open locals.py # Open locals.py
with open(local_setting_file_location) as f: with open(setting_file_location) as f:
local_py = f.read() file_ = f.read()
# Generate a SECRET_KEY that matches the Django standard # Generate a SECRET_KEY that matches the Django standard
SECRET_KEY = get_random_string() SECRET_KEY = get_random_string()
SECRET_KEY = 'CHANGEME!!!' + SECRET_KEY SECRET_KEY = 'CHANGEME!!!' + SECRET_KEY
# Replace "CHANGEME!!!" with SECRET_KEY # Replace "CHANGEME!!!" with SECRET_KEY
local_py = local_py.replace('CHANGEME!!!', SECRET_KEY) file_ = file_.replace('CHANGEME!!!', SECRET_KEY)
# Write the results to the locals.py module # Write the results to the locals.py module
with open(local_setting_file_location, 'w') as f: with open(setting_file_location, 'w') as f:
f.write(local_py) 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): def remove_task_app(project_directory):
"""Removes the taskapp if celery isn't going to be used""" """Removes the taskapp if celery isn't going to be used"""

View File

@ -13,7 +13,6 @@ indent_style = space
indent_size = 4 indent_size = 4
[*.py] [*.py]
# https://github.com/timothycrosley/isort/wiki/isort-Settings
line_length=120 line_length=120
known_first_party={{ cookiecutter.repo_name }} known_first_party={{ cookiecutter.repo_name }}
multi_line_output=3 multi_line_output=3

View File

@ -1,4 +1,3 @@
postgres: postgres:
image: postgres image: postgres
volumes: volumes:

View File

@ -3,8 +3,8 @@ POSTGRES_USER=postgresuser
ADMIN_URL= ADMIN_URL=
DJANGO_SETTINGS_MODULE=config.settings.production DJANGO_SETTINGS_MODULE=config.settings.production
DJANGO_SECRET_KEY= DJANGO_SECRET_KEY=CHANGEME!!!
DJANGO_ALLOWED_HOSTS= DJANGO_ALLOWED_HOSTS=.{{ cookiecutter.domain_name }}
DJANGO_AWS_ACCESS_KEY_ID= DJANGO_AWS_ACCESS_KEY_ID=
DJANGO_AWS_SECRET_ACCESS_KEY= DJANGO_AWS_SECRET_ACCESS_KEY=
DJANGO_AWS_STORAGE_BUCKET_NAME= DJANGO_AWS_STORAGE_BUCKET_NAME=

View File

@ -1,5 +1,5 @@
# Bleeding edge Django # Bleeding edge Django
django==1.8.4 django==1.8.5
# Configuration # Configuration
django-environ==0.4.0 django-environ==0.4.0
@ -18,18 +18,23 @@ django-floppyforms==1.5.2
django-model-utils==2.3.1 django-model-utils==2.3.1
# Images # Images
Pillow==2.9.0 Pillow==3.0.0
# For user registration, either via email or social # For user registration, either via email or social
# Well-built with regular release cycles! # Well-built with regular release cycles!
django-allauth==0.23.0 django-allauth==0.23.0
# 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 psycopg2==2.6.1
{%- endif %}
# Unicode slugification # Unicode slugification
unicode-slugify==0.1.3 unicode-slugify==0.1.3
django-autoslug==1.8.0 django-autoslug==1.9.3
# Time zones support # Time zones support
pytz==2015.6 pytz==2015.6

View File

@ -1,21 +1,21 @@
# Local development dependencies go here # Local development dependencies go here
-r base.txt -r base.txt
coverage==4.0 coverage==4.0.1
Sphinx Sphinx
django-extensions==1.5.7 django-extensions==1.5.7
Werkzeug==0.10.4 Werkzeug==0.10.4
django-test-plus==1.0.9 django-test-plus==1.0.9
factory_boy==2.5.2 factory_boy==2.6.0
# django-debug-toolbar that works with Django 1.5+ # django-debug-toolbar that works with Django 1.5+
django-debug-toolbar==1.3.2 django-debug-toolbar==1.4
# improved REPL # improved REPL
ipdb==0.8.1 ipdb==0.8.1
{% if cookiecutter.use_maildump == "y" -%} {% if cookiecutter.use_maildump == "y" -%}
# Required by maildump. Need to pin dependency to gevent beta to be Python 3-compatible. # Required by maildump. Need to pin dependency to gevent beta to be Python 3-compatible.
gevent==1.1b5 gevent==1.0.2
# Enables better email testing # Enables better email testing
maildump==0.5.1 maildump==0.5.1
{%- endif %} {%- endif %}

View File

@ -2,6 +2,13 @@
# production that isn't in development. # production that isn't in development.
-r base.txt -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 # WSGI Handler
# ------------------------------------------------ # ------------------------------------------------
gevent==1.0.2 gevent==1.0.2

View File

@ -1,5 +1,12 @@
# Test dependencies go here. # Test dependencies go here.
-r base.txt -r base.txt
{% 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 coverage==4.0
flake8==2.4.1 flake8==2.4.1
django-test-plus==1.0.9 django-test-plus==1.0.9

View File

@ -5,7 +5,7 @@ hitchcron==0.2
hitchpostgres==0.6.3 hitchpostgres==0.6.3
hitchpython==0.3.8 hitchpython==0.3.8
hitchredis==0.4.3 hitchredis==0.4.3
hitchselenium==0.4.3 hitchselenium==0.4.5
hitchserve==0.4.5 hitchserve==0.4.5
hitchsmtp==0.2.1 hitchsmtp==0.2.1
hitchtest==0.8.0 hitchtest==0.8.0
@ -14,7 +14,7 @@ ipython==4.0.0
Jinja2==2.8 Jinja2==2.8
MarkupSafe==0.23 MarkupSafe==0.23
patool==1.8 patool==1.8
psutil==3.2.1 psutil==3.2.2
python-build==0.2.3 python-build==0.2.3
pyuv==1.2.0 pyuv==1.2.0
PyYAML==3.11 PyYAML==3.11

View File

@ -4,10 +4,7 @@ import os
from celery import Celery from celery import Celery
from django.apps import AppConfig from django.apps import AppConfig
from django.conf import settings from django.conf import settings
{% if cookiecutter.use_sentry == "y" -%}
from raven import Client
from raven.contrib.celery import register_signal
{%- endif %}
if not settings.configured: if not settings.configured:
# set the default Django settings module for the 'celery' program. # set the default Django settings module for the 'celery' program.
@ -30,6 +27,8 @@ class CeleryConfig(AppConfig):
{% if cookiecutter.use_sentry == "y" -%} {% if cookiecutter.use_sentry == "y" -%}
if hasattr(settings, 'RAVEN_CONFIG'): if hasattr(settings, 'RAVEN_CONFIG'):
# Celery signal registration # Celery signal registration
from raven import Client
from raven.contrib.celery import register_signal
client = Client(dsn=settings.RAVEN_CONFIG['dsn']) client = Client(dsn=settings.RAVEN_CONFIG['dsn'])
register_signal(client) register_signal(client)
{%- endif %} {%- endif %}

View File

@ -31,7 +31,7 @@
<body> <body>
<div class="m-b-lg"> <div class="m-b">
<nav class="navbar navbar-dark navbar-static-top bg-inverse"> <nav class="navbar navbar-dark navbar-static-top bg-inverse">
<div class="container"> <div class="container">
<a class="navbar-brand" href="/">{% endraw %}{{ cookiecutter.project_name }}{% raw %}</a> <a class="navbar-brand" href="/">{% endraw %}{{ cookiecutter.project_name }}{% raw %}</a>
@ -42,17 +42,17 @@
<!-- Collect the nav links, forms, and other content for toggling --> <!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-toggleable-xs" id="bs-navbar-collapse-1"> <div class="collapse navbar-toggleable-xs" id="bs-navbar-collapse-1">
<nav class="nav navbar-nav"> <nav class="nav navbar-nav">
<a class="nav-link nav-item" href="{% url 'home' %}">Home</a></li> <a class="nav-link nav-item" href="{% url 'home' %}">Home</a>
<a class="nav-link nav-item" href="{% url 'about' %}">About</a></li> <a class="nav-link nav-item" href="{% url 'about' %}">About</a>
</nav> </nav>
<nav class="nav navbar-nav pull-right"> <nav class="nav navbar-nav pull-right">
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
<a class="nav-link nav-item" href="{% url 'users:detail' request.user.username %}">{% trans "My Profile" %}</a></li> <a class="nav-link nav-item" href="{% url 'users:detail' request.user.username %}">{% trans "My Profile" %}</a>
<a class="nav-link nav-item" href="{% url 'account_logout' %}">{% trans "Logout" %}</a></li> <a class="nav-link nav-item" href="{% url 'account_logout' %}">{% trans "Logout" %}</a>
{% else %} {% else %}
<a class="nav-link nav-item" href="{% url 'account_signup' %}">{% trans "Sign Up" %}</a></li> <a class="nav-link nav-item" href="{% url 'account_signup' %}">{% trans "Sign Up" %}</a>
<a class="nav-link nav-item" href="{% url 'account_login' %}">{% trans "Log In" %}</a></li> <a class="nav-link nav-item" href="{% url 'account_login' %}">{% trans "Log In" %}</a>
{% endif %} {% endif %}
</nav> </nav>
</div> </div>