This document describes how to get started with Silver Lining using
Creating a Layout
First thing you have to do (after installing Silver Lining of course)
is create an environment for your new application. Do that like::
$ silver init sampleapp
This creates a directory ``sampleapp/`` with a basic layout. The
first thing we'll do is set up version control for our project.
For the sake of documentation, imagine you go to `bitbucket
<http://bitbucket.org>`_ and create two new repositories, one called
``sampleapp`` and another called ``sampleapp-lib`` (and for the
examples we'll use the username ``USER``).
We'll go into our new environment and use these::
$ cd sampleapp
$ hg clone http://bitbucket.org/USER/sampleapp src/sampleapp
$ rm -r lib/python/
$ hg clone http://bitbucket.org/USER/sampleapp-lib lib/python
$ mkdir lib/python/bin/
$ echo "syntax: glob
" > lib/python/.hgignore
$ mv bin/* lib/python/bin/
$ rmdir bin/
$ ln -s lib/python/bin bin
Now there is a basic layout setup, with all your libraries going into
the ``sampleapp-lib`` repository, and your main application in the
Next we'll install Django::
$ source bin/activate
$ pip install Django
Then we'll set up a standard Django site::
$ cd src/sampleapp
$ django-admin.py startproject sampleapp
Also we'd like to be able to import this file. It'd be nice if there
was a ``setup.py`` file, and we could run ``pip -e src/sampleapp``,
but ``django-admin.py`` doesn't create that itself. Instead we'll get
that on the import path more manually with a ``.pth`` file::
$ echo "../../src/sampleapp" > lib/python/sampleapp.pth
That files will cause ``../../src/sampleapp`` (relative to the .pth
file itself) to be on ``sys.path``, which means when you run ``from
sampleapp import settings`` (for example) it will know to find it in
``src/sampleapp/sampleapp/settings.py``. Not all Django projects are
setup this way -- applications are often not in a namespace, for
example. But I think it's simply good practice to keep code
partitioned into namespaces.
Also there's the tricky ``$DJANGO_SETTINGS_MODULE`` that you might
have had problems with before. We'll use the file
``lib/python/silvercustomize.py`` (which is imported everytime Python is
started) to make sure that is always set::
$ echo "import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'sampleapp.settings'
" > lib/python/silvercustomize.py
Also we have a file ``src/sampleapp/sampleapp/manage.py``, and that
file doesn't work *quite* how we'd like. Instead we'll put a file
into ``bin/manage.py`` that does the same thing::
$ rm sampleapp/manage.py
$ cd ../..
$ echo '#!/usr/bin/env python
from django.core.management import execute_manager
from sampleapp import settings
if __name__ == "__main__":
' > bin/manage.py
$ chmod +x bin/manage.py
Now, if you were just using plain Django you'd do something like run
``python manage.py runserver``. But we'll be using ``silver serve``
instead, which means we have to set up the two other files Silver
Lining needs: ``app.ini`` and the runner. Here's a simple
$ echo '[production]
app_name = sampleapp
runner = src/sampleapp/silver-runner.py
' > src/sampleapp/silver-app.ini
$ rm app.ini
$ ln -s src/sampleapp/silver-app.ini app.ini
The file *must* be in the "root" of your application, and named
``app.ini``, but it's good to keep it in version control, so we set it
up with a symlink.
It also refers to a "runner", which is the Python file that loads up
the WSGI application. This looks about the same for any Django
application, and we'll put it in ``src/sampleapp/silver-runner.py``::
$ echo 'import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
' > src/sampleapp/silver-runner.py
Now if you want to run the application, you can::
$ silver serve .
This will load it up on ``http://localhost:8080``, and serve up a
boring page. To do something interesting we'll want to use a
Setting Up A Database
At the moment the only good database to use is PostgreSQL with the
PostGIS extensions. Add this line to ``app.ini``::
This makes the database "available" to the application. For
development you still have to set it up yourself. You should create a
database ``sampleapp`` on your computer.
Next, we'll need to change ``settings.py`` to use the new database
configuration. Here's the lines that you'll see::
DATABASE_ENGINE = '' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
DATABASE_NAME = '' # Or path to database file if using sqlite3.
DATABASE_USER = '' # Not used with sqlite3.
DATABASE_PASSWORD = '' # Not used with sqlite3.
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
First add this to the top of the file::
Then you'll change those lines to::
DATABASE_ENGINE = 'postgresql_psycopg2'
DATABASE_NAME = os.environ['CONFIG_PG_DBNAME']
DATABASE_USER = os.environ['CONFIG_PG_USER']
DATABASE_PASSWORD = os.environ['CONFIG_PG_PASSWORD']
DATABASE_HOST = os.environ['CONFIG_PG_HOST']
DATABASE_PORT = ''
Now we can create all the default tables::
$ manage.py syncdb
Creating table auth_permission
Creating table auth_group
Creating table auth_user
Creating table auth_message
Creating table django_content_type
Creating table django_session
Creating table django_site
Now we have an empty project that doesn't do anything. Let's make it
do a little something (this is all really based on `the Django
$ manage.py startapp polls
Django magically knows to put the code in
``src/sampleapp/sampleapp/polls/`` -- we'll setup the model in
from django.db import models
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
poll = models.ForeignKey(Poll)
choice = models.CharField(max_length=200)
votes = models.IntegerField()
And activate the application by adding ``'sampleapp.polls'`` to
``INSTALLED_APPS`` in ``src/sampleapp/sampleapp/settings.py``. Also
add ``'django.contrib.admin'`` to get the admin app in place. Run
``manage.py syncdb`` to get the tables in place.
You can try ``silver serve .`` and go to ``/admin/`` to login and
see your tables. You might notice all the CSS is broken.
Silver Lining serves static files out of the ``static/`` directory.
You don't actually put ``static`` in the URLs, these files are
available at the top-level (unless you create a ``static/static/``
directory). The best way to put files in there is generally symbolic
For Django admin, do this::
$ cd static
$ ln -s ../lib/python/django/contrib/admin/media admin-media
Now edit ``src/sampleapp/sampleapp/settings.py`` and change
``ADMIN_MEDIA_PREFIX`` to ``'/admin-media'``.
FIXME: probably some other links should be added.
One *last* little thing you might want to do; replace this line in
SECRET_KEY = 'ASF#@$@#JFAS#@'
from silversupport.secret import get_secret
SECRET_KEY = get_secret()
Then you don't have to worry about checking a secret into version
Setting Up Your Deployed Database
After you write an app and are ready to deploy it, you just run
``silver update``. *But*, while you'll get a blank database to
use, it will be empty until you run ``syncdb``. A good way to do that
$ silver run HOSTNAME manage.py syncdb
This runs ``bin/manage.py`` on the host named ``HOSTNAME``. You can
use this for imports or other management tasks as well.
A more robust mechanism is to use the ``update_fetch`` setting in
``app.ini``: this is a URL (provided *by* your application) that is
fetched everytime your application is updated. This URL can check the
database, create tables, etc. (In the future I expect this can use
scripts in addition to URLs, at which point you can run ``syncdb``
directly; for now you could also create a URL in your app that calls