First commit
commit
f4d828fa39
|
@ -0,0 +1,12 @@
|
|||
syntax: glob
|
||||
|
||||
*.json
|
||||
*.gunicorn.*
|
||||
*.pyc
|
||||
|
||||
db.db
|
||||
local_settings.py
|
||||
logs
|
||||
media/admin
|
||||
media/cache
|
||||
media/css/style.css
|
|
@ -0,0 +1,28 @@
|
|||
import os
|
||||
import sys
|
||||
import site
|
||||
|
||||
parent = os.path.dirname
|
||||
site_dir = parent(os.path.abspath(__file__))
|
||||
project_dir = parent(parent(os.path.abspath(__file__)))
|
||||
|
||||
sys.path.insert(0, project_dir)
|
||||
sys.path.insert(0, site_dir)
|
||||
|
||||
import local_settings
|
||||
site.addsitedir(local_settings.VIRTUALENV_PATH)
|
||||
|
||||
from django.core.management import setup_environ
|
||||
import settings
|
||||
setup_environ(settings)
|
||||
|
||||
import django.core.handlers.wsgi
|
||||
application = django.core.handlers.wsgi.WSGIHandler()
|
||||
|
||||
from werkzeug.debug import DebuggedApplication
|
||||
application = DebuggedApplication(application, evalex=True)
|
||||
|
||||
def null_technical_500_response(request, exc_type, exc_value, tb):
|
||||
raise exc_type, exc_value, tb
|
||||
from django.views import debug
|
||||
debug.technical_500_response = null_technical_500_response
|
|
@ -0,0 +1,215 @@
|
|||
from __future__ import with_statement
|
||||
|
||||
import os
|
||||
from fabric.api import *
|
||||
from dwfab.misc import growl as _growl
|
||||
|
||||
|
||||
UPLOADS_DIR = 'media/uploads'
|
||||
APPS_TO_SYNC = [
|
||||
'auth',
|
||||
'contenttypes',
|
||||
'redirects',
|
||||
'registration',
|
||||
]
|
||||
|
||||
def prod():
|
||||
'''Run on the production site.'''
|
||||
env.env_name = 'production'
|
||||
env.hosts = ['nick@beta.snipt.net:38038']
|
||||
env.process_name = 'beta-snipt'
|
||||
env.site_path = '/var/www/beta-snipt'
|
||||
env.venv_path = '/home/nick/.virtualenvs/beta-snipt'
|
||||
env.site_url = 'https://beta.snipt.net/'
|
||||
env.uploads_path = env.site_path + '/' + UPLOADS_DIR
|
||||
|
||||
|
||||
def _python(cmd):
|
||||
return env.venv_path.rstrip('/') + '/bin/python ' + cmd
|
||||
def _lpython(cmd):
|
||||
return os.getenv('VIRTUAL_ENV').rstrip('/') + '/bin/python ' + cmd
|
||||
def _pip(cmd):
|
||||
return env.venv_path.rstrip('/') + '/bin/pip ' + cmd
|
||||
|
||||
|
||||
def pull_uploads():
|
||||
'''Copy the uploads from the site to your local machine.'''
|
||||
require('uploads_path', provided_by=['prod'])
|
||||
|
||||
sudo('chmod -R a+r "%s"' % env.uploads_path)
|
||||
|
||||
rsync_command = r"""rsync -av -e 'ssh -p %s' %s@%s:%s %s""" % (
|
||||
env.port,
|
||||
env.user, env.host,
|
||||
env.uploads_path.rstrip('/') + '/',
|
||||
UPLOADS_DIR.rstrip('/')
|
||||
)
|
||||
print local(rsync_command, capture=False)
|
||||
|
||||
def pull_data():
|
||||
'''Copy the data from the site to your local machine.'''
|
||||
require('site_path', provided_by=['prod'])
|
||||
require('venv_path', provided_by=['prod'])
|
||||
|
||||
for app in APPS_TO_SYNC:
|
||||
local(_lpython('manage.py reset --noinput %s' % app))
|
||||
local(_lpython('manage.py migrate --fake %s' % app))
|
||||
|
||||
for app in APPS_TO_SYNC:
|
||||
with cd(env.site_path):
|
||||
sudo(_python('manage.py dumpdata --format=json --indent=2 --natural ' +
|
||||
'%s > snipt-fixtures-%s.json' % (app, app)))
|
||||
get('%s/snipt-fixtures-%s.json' % (env.site_path, app), 'snipt-fixtures-%s.json' % app)
|
||||
|
||||
local(_lpython('manage.py loaddata snipt-fixtures-%s.json' % app))
|
||||
|
||||
def pull_all():
|
||||
'''Copy the uploads and data from the site to your local machine.'''
|
||||
pull_uploads()
|
||||
pull_data()
|
||||
_growl('Snipt: Pull Complete', 'The database and uploads have been refreshed.')
|
||||
|
||||
|
||||
def reindex():
|
||||
require('site_path', provided_by=['prod'])
|
||||
|
||||
with cd(env.site_path):
|
||||
sudo(_python('manage.py rebuild_index --noinput'))
|
||||
|
||||
|
||||
def syncdb():
|
||||
'''Run syncdb.'''
|
||||
require('site_path', provided_by=['prod'])
|
||||
require('venv_path', provided_by=['prod'])
|
||||
|
||||
with cd(env.site_path):
|
||||
sudo(_python('manage.py syncdb'))
|
||||
|
||||
def migrate():
|
||||
'''Run any needed migrations.'''
|
||||
require('site_path', provided_by=['prod'])
|
||||
require('venv_path', provided_by=['prod'])
|
||||
|
||||
with cd(env.site_path):
|
||||
sudo(_python('manage.py migrate'))
|
||||
|
||||
def requirements():
|
||||
'''Copy local requirements.txt to the site and install requirements.'''
|
||||
require('site_path', provided_by=['prod'])
|
||||
require('venv_path', provided_by=['prod'])
|
||||
|
||||
with cd(env.site_path):
|
||||
put('requirements.txt', 'requirements.txt')
|
||||
run(_pip('install -r requirements.txt'))
|
||||
run('hg revert requirements.txt')
|
||||
|
||||
|
||||
def retag():
|
||||
'''Check which revision the site is at and update the local tag.
|
||||
|
||||
Useful if someone else has deployed (which makes your production/staging local
|
||||
tag incorrect.
|
||||
'''
|
||||
require('site_path', provided_by=['prod'])
|
||||
require('env_name', provided_by=['prod'])
|
||||
|
||||
with cd(env.site_path):
|
||||
current = run('hg id --rev . --quiet').strip(' \n+')
|
||||
|
||||
local('hg tag --local --force %s --rev %s' % (env.env_name, current))
|
||||
|
||||
def deploy(rev='.'):
|
||||
'''Deploy your current revision to the site.
|
||||
|
||||
You can also specify a different revision to deploy by passing an argument:
|
||||
|
||||
fab stag deploy:1a2cc06d
|
||||
|
||||
You can use your local revision numbers as arguments -- the full hash will be
|
||||
looked up and used.
|
||||
'''
|
||||
require('site_path', provided_by=['prod'])
|
||||
|
||||
rev = local('hg id --rev %s --quiet' % rev).strip(' \n+')
|
||||
|
||||
local('hg push --rev %s' % rev)
|
||||
|
||||
with cd(env.site_path):
|
||||
run('hg tag --local --force previous')
|
||||
run('hg pull --rev %s' % rev)
|
||||
run('hg update --rev %s' % rev)
|
||||
|
||||
retag()
|
||||
|
||||
syncdb()
|
||||
migrate()
|
||||
|
||||
restart()
|
||||
check()
|
||||
|
||||
|
||||
def deploy_template(rev='.'):
|
||||
'''Deploy your current revision to the site, without restarting the server.
|
||||
|
||||
You can also specify a different revision to deploy by passing an argument:
|
||||
|
||||
fab stag deploy:1a2cc06d
|
||||
|
||||
You can use your local revision numbers as arguments -- the full hash will be
|
||||
looked up and used.
|
||||
'''
|
||||
require('site_path', provided_by=['prod'])
|
||||
|
||||
rev = local('hg id --rev %s --quiet' % rev).strip(' \n+')
|
||||
|
||||
local('hg push --rev %s' % rev)
|
||||
|
||||
with cd(env.site_path):
|
||||
run('hg tag --local --force previous')
|
||||
run('hg pull --rev %s' % rev)
|
||||
run('hg update --rev %s' % rev)
|
||||
|
||||
retag()
|
||||
check()
|
||||
|
||||
|
||||
def rollback():
|
||||
'''Roll the site back to the version it was at before the last deployment.
|
||||
|
||||
Things may break if migrations were made between the versions. TODO: Fix this.
|
||||
'''
|
||||
require('site_path', provided_by=['prod'])
|
||||
|
||||
with cd(env.site_path):
|
||||
run('hg update previous')
|
||||
|
||||
retag()
|
||||
restart()
|
||||
check()
|
||||
|
||||
def check():
|
||||
'''Check that the home page of the site returns an HTTP 200.
|
||||
|
||||
If it does, a normal growl message is sent.
|
||||
|
||||
If it does not, a warning is issued and a sticky growl message is sent.
|
||||
'''
|
||||
require('site_url', provided_by=['prod'])
|
||||
|
||||
if not '200 OK' in run('curl --silent -I "%s"' % env.site_url):
|
||||
warn("Something is wrong (we didn't get a 200 response)!")
|
||||
_growl('Snipt: DEPLOYMENT ERROR', 'Something went wrong. Please investigate.', sticky=True)
|
||||
else:
|
||||
_growl('Snipt: Deployment Complete', 'Deployment finished, site is working.')
|
||||
|
||||
def restart():
|
||||
'''Restart the site's gunicorn server.'''
|
||||
require('site_path', provided_by=['prod'])
|
||||
require('process_name', provided_by=['prod'])
|
||||
|
||||
sudo('supervisorctl restart %s' % env.process_name)
|
||||
|
||||
with cd(env.site_path):
|
||||
sudo('chmod a+r media/css/*.css')
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
gunicorn -c gunicorn.conf.py debug_wsgi:application
|
|
@ -0,0 +1,21 @@
|
|||
bind = "unix:/tmp/gunicorn.snipt.sock"
|
||||
daemon = True # Whether work in the background
|
||||
debug = False # Some extra logging
|
||||
logfile = ".gunicorn.log" # Name of the log file
|
||||
loglevel = "info" # The level at which to log
|
||||
pidfile = ".gunicorn.pid" # Path to a PID file
|
||||
workers = 1 # Number of workers to initialize
|
||||
umask = 0 # Umask to set when daemonizing
|
||||
user = None # Change process owner to user
|
||||
group = None # Change process group to group
|
||||
proc_name = "gunicorn-snipt" # Change the process name
|
||||
tmp_upload_dir = None # Set path used to store temporary uploads
|
||||
|
||||
|
||||
def post_fork(server, worker):
|
||||
server.log.info("Worker spawned (pid: %s)" % worker.pid)
|
||||
|
||||
import local_settings, monitor
|
||||
if local_settings.DEBUG:
|
||||
server.log.info("Starting change monitor.")
|
||||
monitor.start(interval=1.0)
|
|
@ -0,0 +1,21 @@
|
|||
bind = "unix:/tmp/gunicorn.snipt.sock"
|
||||
daemon = False # Whether work in the background
|
||||
debug = False # Some extra logging
|
||||
logfile = ".gunicorn.log" # Name of the log file
|
||||
loglevel = "info" # The level at which to log
|
||||
pidfile = ".gunicorn.pid" # Path to a PID file
|
||||
workers = 9 # Number of workers to initialize
|
||||
umask = 0 # Umask to set when daemonizing
|
||||
user = None # Change process owner to user
|
||||
group = None # Change process group to group
|
||||
proc_name = "gunicorn-snipt" # Change the process name
|
||||
tmp_upload_dir = None # Set path used to store temporary uploads
|
||||
|
||||
|
||||
def post_fork(server, worker):
|
||||
server.log.info("Worker spawned (pid: %s)" % worker.pid)
|
||||
|
||||
import local_settings, monitor
|
||||
if local_settings.DEBUG:
|
||||
server.log.info("Starting change monitor.")
|
||||
monitor.start(interval=1.0)
|
|
@ -0,0 +1,20 @@
|
|||
# Copy this file to local_settings.py and change it as needed.
|
||||
|
||||
DEBUG = True
|
||||
TEMPLATE_DEBUG = DEBUG
|
||||
|
||||
EMAIL_BACKEND = 'postmark.backends.PostmarkBackend'
|
||||
POSTMARK_API_KEY = ''
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'sqlite3',
|
||||
'NAME': '/path/to/db/',
|
||||
'USER': '',
|
||||
'PASSWORD': '',
|
||||
'HOST': '',
|
||||
'PORT': '',
|
||||
}
|
||||
}
|
||||
|
||||
VIRTUALENV_PATH = '/path/to/virtualenv/'
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
from django.core.management import execute_manager
|
||||
try:
|
||||
import settings # Assumed to be in the same directory.
|
||||
except ImportError:
|
||||
import sys
|
||||
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
execute_manager(settings)
|
|
@ -0,0 +1,48 @@
|
|||
/* http://meyerweb.com/eric/tools/css/reset/
|
||||
v2.0 | 20110126
|
||||
License: none (public domain)
|
||||
*/
|
||||
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
// Fonts
|
||||
@Helvetica: 'Helvetica Neue', Helvetica, Arial, 'Liberation Sans', FreeSans, sans-serif;
|
||||
|
||||
// Focus
|
||||
*:focus {
|
||||
.box-shadow(0, 0, 10px, #47B7F2);
|
||||
}
|
||||
|
||||
// Mixins
|
||||
.border-radius(@radius: 5px) {
|
||||
-webkit-background-clip: padding-box;
|
||||
-webkit-border-radius: @radius;
|
||||
-moz-background-clip: padding-box;
|
||||
-moz-border-radius: @radius;
|
||||
border-radius: @radius;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
.box-shadow(@horizontal: 0px, @vertical: 1px, @blur: 2px, @color: #CCC) {
|
||||
-webkit-box-shadow: @horizontal @vertical @blur @color;
|
||||
-moz-box-shadow: @horizontal @vertical @blur @color;
|
||||
box-shadow: @horizontal @vertical @blur @color;
|
||||
}
|
||||
.inset-box-shadow(@horizontal: 0px, @vertical: 1px, @blur: 2px, @color: #CCC) {
|
||||
-webkit-box-shadow: inset @horizontal @vertical @blur @color;
|
||||
-moz-box-shadow: inset @horizontal @vertical @blur @color;
|
||||
box-shadow: inset @horizontal @vertical @blur @color;
|
||||
}
|
||||
.multi-color-border(@top, @sides, @bottom) {
|
||||
border-top: 1px solid @top;
|
||||
border-left: 1px solid @sides;
|
||||
border-right: 1px solid @sides;
|
||||
border-bottom: 1px solid @bottom;
|
||||
}
|
||||
.multi-border-radius(@topLeft: 5px, @topRight: 5px, @bottomRight: 5px, @bottomLeft: 5px) {
|
||||
-webkit-border-top-left-radius: @topLeft;
|
||||
-webkit-border-top-right-radius: @topRight;
|
||||
-webkit-border-bottom-right-radius: @bottomRight;
|
||||
-webkit-border-bottom-left-radius: @bottomLeft;
|
||||
-moz-border-radius-topleft: @topLeft;
|
||||
-moz-border-radius-topright: @topRight;
|
||||
-moz-border-radius-bottomright: @bottomRight;
|
||||
-moz-border-radius-bottomleft: @bottomLeft;
|
||||
border-top-left-radius: @topLeft;
|
||||
border-top-right-radius: @topRight;
|
||||
border-bottom-right-radius: @bottomRight;
|
||||
border-bottom-left-radius: @bottomLeft;
|
||||
}
|
||||
.vertical-gradient(@start: #000, @stop: #FFF) { background: (@start + @stop) / 2;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(@start), to(@stop));
|
||||
background: -moz-linear-gradient(center top, @start 0%, @stop 100%);
|
||||
background: -moz-gradient(center top, @start 0%, @stop 100%);
|
||||
}
|
||||
.vertical-gradient-with-image(@start: #000, @stop: #FFF, @image) {
|
||||
background: (@start + @stop) / 2 @image;
|
||||
background: @image, -webkit-gradient(linear, left top, left bottom, from(@start), to(@stop));
|
||||
background: @image, -moz-linear-gradient(center top, @start 0%, @stop 100%);
|
||||
background: @image, -moz-gradient(center top, @start 0%, @stop 100%);
|
||||
}
|
||||
|
||||
// Page
|
||||
html, body {
|
||||
background-color: #FFF;
|
||||
}
|
||||
body {
|
||||
color: #666;
|
||||
font: normal 14px @Helvetica;
|
||||
overflow-y: scroll;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
// Utils
|
||||
.group:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1 @@
|
|||
$(function() {});
|
|
@ -0,0 +1,113 @@
|
|||
import os
|
||||
import sys
|
||||
import time
|
||||
import signal
|
||||
import threading
|
||||
import atexit
|
||||
import Queue
|
||||
|
||||
_interval = 1.0
|
||||
_times = {}
|
||||
_files = []
|
||||
|
||||
_running = False
|
||||
_queue = Queue.Queue()
|
||||
_lock = threading.Lock()
|
||||
|
||||
def _restart(path):
|
||||
_queue.put(True)
|
||||
prefix = 'monitor (pid=%d):' % os.getpid()
|
||||
print >> sys.stderr, '%s Change detected to \'%s\'.' % (prefix, path)
|
||||
print >> sys.stderr, '%s Triggering process restart.' % prefix
|
||||
os.kill(os.getpid(), signal.SIGINT)
|
||||
|
||||
def _modified(path):
|
||||
try:
|
||||
# If path doesn't denote a file and were previously
|
||||
# tracking it, then it has been removed or the file type
|
||||
# has changed so force a restart. If not previously
|
||||
# tracking the file then we can ignore it as probably
|
||||
# pseudo reference such as when file extracted from a
|
||||
# collection of modules contained in a zip file.
|
||||
|
||||
if not os.path.isfile(path):
|
||||
return path in _times
|
||||
|
||||
# Check for when file last modified.
|
||||
|
||||
mtime = os.stat(path).st_mtime
|
||||
if path not in _times:
|
||||
_times[path] = mtime
|
||||
|
||||
# Force restart when modification time has changed, even
|
||||
# if time now older, as that could indicate older file
|
||||
# has been restored.
|
||||
|
||||
if mtime != _times[path]:
|
||||
return True
|
||||
except:
|
||||
# If any exception occured, likely that file has been
|
||||
# been removed just before stat(), so force a restart.
|
||||
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _monitor():
|
||||
while 1:
|
||||
# Check modification times on all files in sys.modules.
|
||||
|
||||
for module in sys.modules.values():
|
||||
if not hasattr(module, '__file__'):
|
||||
continue
|
||||
path = getattr(module, '__file__')
|
||||
if not path:
|
||||
continue
|
||||
if os.path.splitext(path)[1] in ['.pyc', '.pyo', '.pyd']:
|
||||
path = path[:-1]
|
||||
if _modified(path):
|
||||
return _restart(path)
|
||||
|
||||
# Check modification times on files which have
|
||||
# specifically been registered for monitoring.
|
||||
|
||||
for path in _files:
|
||||
if _modified(path):
|
||||
return _restart(path)
|
||||
|
||||
# Go to sleep for specified interval.
|
||||
|
||||
try:
|
||||
return _queue.get(timeout=_interval)
|
||||
except:
|
||||
pass
|
||||
|
||||
_thread = threading.Thread(target=_monitor)
|
||||
_thread.setDaemon(True)
|
||||
|
||||
def _exiting():
|
||||
try:
|
||||
_queue.put(True)
|
||||
except:
|
||||
pass
|
||||
_thread.join()
|
||||
|
||||
atexit.register(_exiting)
|
||||
|
||||
def track(path):
|
||||
if not path in _files:
|
||||
_files.append(path)
|
||||
|
||||
def start(interval=1.0):
|
||||
global _interval
|
||||
if interval < _interval:
|
||||
_interval = interval
|
||||
|
||||
global _running
|
||||
_lock.acquire()
|
||||
if not _running:
|
||||
prefix = 'monitor (pid=%d):' % os.getpid()
|
||||
print >> sys.stderr, '%s Starting change monitor.' % prefix
|
||||
_running = True
|
||||
_thread.start()
|
||||
_lock.release()
|
|
@ -0,0 +1,24 @@
|
|||
# Django
|
||||
-e git://github.com/django/django.git@1.3.X#egg=django
|
||||
-e git://github.com/dziegler/django-css.git#egg=django-css
|
||||
-e git://github.com/django-extensions/django-extensions.git#egg=django_extensions
|
||||
-e hg+http://bitbucket.org/offline/django-annoying#egg=django-annoying
|
||||
-e git://github.com/alex/django-templatetag-sugar.git#egg=templatetag_sugar
|
||||
-e hg+http://bitbucket.org/dwaiter/django-bcrypt#egg=django-bcrypt
|
||||
-e hg+ssh://hg@bitbucket.org/nicksergeant/django-registration#egg=django-registration
|
||||
|
||||
# Admin
|
||||
-e svn+http://django-grappelli.googlecode.com/svn/trunk#egg=django-grappelli
|
||||
-e hg+http://bitbucket.org/fetzig/grappelli-admin-tools#egg=admin_tools
|
||||
|
||||
# Deployment
|
||||
-e git://github.com/bitprophet/fabric.git#egg=fabric
|
||||
-e git+http://github.com/benoitc/gunicorn.git#egg=gunicorn
|
||||
-e hg+ssh://hg@bitbucket.org/nicksergeant/dwfab#egg=dwfab
|
||||
|
||||
BeautifulSoup
|
||||
django-postmark
|
||||
johnny-cache
|
||||
python-memcached
|
||||
South
|
||||
Werkzeug
|
|
@ -0,0 +1,90 @@
|
|||
import os.path
|
||||
|
||||
BASE_PATH = os.path.dirname(__file__)
|
||||
|
||||
ADMINS = (
|
||||
('Nick Sergeant', 'nick@snipt.net'),
|
||||
)
|
||||
MANAGERS = ADMINS
|
||||
|
||||
INTERNAL_IPS = ('127.0.0.1',)
|
||||
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
LOGIN_URL = '/login/'
|
||||
LOGOUT_URL = '/logout/'
|
||||
|
||||
TIME_ZONE = 'America/New_York'
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
SITE_ID = 1
|
||||
USE_I18N = True
|
||||
|
||||
MEDIA_ROOT = os.path.join(BASE_PATH, 'media')
|
||||
MEDIA_URL = '/media/'
|
||||
ADMIN_MEDIA_PREFIX = '/media/admin/'
|
||||
|
||||
SECRET_KEY = 'm5w4e9^9r69f!6b9qio%)_p%a*1d(waqki+r_g11=qijh=#wuk'
|
||||
|
||||
SESSION_COOKIE_AGE = 31556926
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS = (
|
||||
'django.core.context_processors.auth',
|
||||
'django.core.context_processors.debug',
|
||||
'django.core.context_processors.i18n',
|
||||
'django.core.context_processors.media',
|
||||
'django.core.context_processors.request',
|
||||
'grappelli.context_processors.admin_template_path',
|
||||
)
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.filesystem.load_template_source',
|
||||
'django.template.loaders.app_directories.load_template_source',
|
||||
)
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfResponseMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
'django.contrib.redirects.middleware.RedirectFallbackMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'urls'
|
||||
|
||||
TEMPLATE_DIRS = os.path.join(BASE_PATH, 'templates')
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'grappelli',
|
||||
'admin_tools.theming',
|
||||
'admin_tools.menu',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.humanize',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.redirects',
|
||||
|
||||
'compressor',
|
||||
'django_bcrypt',
|
||||
'south',
|
||||
)
|
||||
|
||||
# CSS compression
|
||||
|
||||
COMPRESS_OUTPUT_DIR = "cache"
|
||||
COMPILER_FORMATS = {
|
||||
'.less': {
|
||||
'binary_path':'lessc',
|
||||
'arguments': '*.less *.css'
|
||||
},
|
||||
}
|
||||
|
||||
# Grappelli
|
||||
|
||||
GRAPPELLI_ADMIN_TITLE = '<a href="/">Snipt</a>'
|
||||
|
||||
# Local settings and debug
|
||||
|
||||
from local_settings import *
|
||||
|
||||
if DEBUG:
|
||||
INSTALLED_APPS += ('django_extensions',)
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
ln -s "$VIRTUAL_ENV/src/django-grappelli/grappelli/media" "media/admin"
|
|
@ -0,0 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block page-title %}Page Not Found - {{ block.super }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
404: Page Not Found
|
||||
{% endblock %}
|
|
@ -0,0 +1,8 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block page-title %}Server Error - {{ block.super }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
500: Server Error
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" class="{% block html-class %}{% endblock %}">
|
||||
<head>
|
||||
<title>{% block page-title %}Snipt{% endblock %}</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="Long-term memory for coders. Share and store code snippets." />
|
||||
|
||||
{% load compress %}
|
||||
|
||||
{% compress css %}
|
||||
<link rel="stylesheet" href="/media/css/reset.css" />
|
||||
{% if not debug %}
|
||||
<link rel="stylesheet" href="/media/css/style.less" />
|
||||
{% endif %}
|
||||
{% endcompress %}
|
||||
{% if debug %}
|
||||
<link rel="stylesheet/less" href="/media/css/style.less" />
|
||||
{% endif %}
|
||||
|
||||
{% compress js %}
|
||||
<script type="text/javascript" src="/media/js/jquery.js"></script>
|
||||
<script type="text/javascript" src="/media/js/script.js"></script>
|
||||
{% if debug %}
|
||||
<script type="text/javascript" src="/media/js/less.js"></script>
|
||||
{% endif %}
|
||||
{% endcompress %}
|
||||
|
||||
<!--[if IE]>
|
||||
<style type="text/css">
|
||||
.group {
|
||||
display: block;
|
||||
zoom: 1;
|
||||
}
|
||||
</style>
|
||||
<![endif]-->
|
||||
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
</head>
|
||||
<body class="{% block body-class %}{% endblock %}">
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
|
||||
{% if not debug %}
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-514462-44']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga);
|
||||
})();
|
||||
//]]>
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,5 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
Home
|
||||
{% endblock %}
|
|
@ -0,0 +1,19 @@
|
|||
from django.views.generic.simple import direct_to_template
|
||||
from django.conf.urls.defaults import *
|
||||
from django.contrib import admin
|
||||
|
||||
admin.autodiscover()
|
||||
|
||||
from views import home
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
url(r'^admin_tools/', include('admin_tools.urls')),
|
||||
url(r'^grappelli/', include('grappelli.urls')),
|
||||
|
||||
url(r'^404/$', direct_to_template, {'template': '404.html'}),
|
||||
url(r'^500/$', direct_to_template, {'template': '500.html'}),
|
||||
|
||||
url(r'^$', home),
|
||||
)
|
Loading…
Reference in New Issue