Apr 17

Installing GeoDjango with PostgreSQL and zc.buildout

The installation of the PostgreSQL requirements is somewhat daunting. I've spent a bit of time putting together a buildout.cfg to try to make this easier.

I've been wanting to play with GeoDjango for a while, since my database of choice (PostgreSQL) has excellent spatial support. However, getting all the dependencies up and running is pretty complicated.

I've been working on a buildout to get at least most of the steps done for you. There are a couple of manual steps at the end, which I hope to automate when I next have time to work on this.

The buildout installs the following items:

  • PostgreSQL
  • PostGIS
  • GDAL
  • Proj
  • GEOS
  • psycopg2
  • Django

It should also perform initial setup of the PostGIS database template, loading some sample SQL files, and sets up some convenience symlinks for the PostgreSQL command-line programs.

It's not finished - in particular, it just assumes that the user running the buildout is to be used as the database owner and such like. Anyway, here it is:

 

[buildout]
parts =
postgresql
postgis
gdal
init-pgsql
pgsql-symlinks
django

eggs =
psycopg2

[postgresql]
recipe = zc.recipe.cmmi
url = http://wwwmaster.postgresql.org/redir/198/h/source/v8.3.7/postgresql-8.3.7.tar.gz
extra_options =
--with-readline
--enable-thread-safety

[postgis]
recipe = hexagonit.recipe.cmmi
url = http://postgis.refractions.net/download/postgis-1.3.5.tar.gz
configure-options =
--with-pgsql=${postgresql:location}/bin/pg_config
--with-geos=${geos:location}/bin/geos-config
--with-proj=${proj:location}

[proj]
recipe = zc.recipe.cmmi
url = http://download.osgeo.org/proj/proj-4.6.1.tar.gz

[geos]
recipe = zc.recipe.cmmi
url = http://download.osgeo.org/geos/geos-3.0.3.tar.bz2

[gdal]
recipe = zc.recipe.cmmi
url = http://download.osgeo.org/gdal/gdal-1.6.0.tar.gz
extra_options =
--with-python
--with-geos=${geos:location}/bin/geos-config

[init-pgsql]
recipe = iw.recipe.cmd
on_install = true
on_update = false
cmds =
${postgresql:location}/bin/initdb -D ${postgresql:location}/var/data -E UNICODE
${postgresql:location}/bin/pg_ctl -D ${postgresql:location}/var/data start
sleep 30
${postgresql:location}/bin/createdb -E UTF8 template_postgis
${postgresql:location}/bin/createlang -d template_postgis plpgsql
${postgresql:location}/bin/psql -d template_postgis -f ${postgis:location}/share/lwpostgis.sql
${postgresql:location}/bin/psql -d template_postgis -f ${postgis:location}/share/spatial_ref_sys.sql
${postgresql:location}/bin/psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;"
${postgresql:location}/bin/psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"
${postgresql:location}/bin/pg_ctl -D ${postgresql:location}/var/data stop

[pgsql-symlinks]
recipe = cns.recipe.symlink
symlink_target = ${buildout:directory}/bin
symlink_base = ${postgresql:location}/bin
symlink =
clusterdb
createdb
createlang
createuser
dropdb
droplang
dropuser
ecpg
initdb
ipcclean
pg_config
pg_controldata
pg_ctl
pg_dump
pg_dumpall
pg_resetxlog
pg_restore
postgres
postmaster
psql
reindexdb
vacuumdb

[django]
recipe = djangorecipe
version = 1.0.2
project = project
eggs =
${buildout:eggs}

Note that running this will actually attempt to start up and shut down the database server, as it needs to be running in order for some of the initialisation scripts to run. That 'sleep 30' in the middle is to allow the database server to start, and (if you're on OS X and running it) to give you a change to enter your username and password for the firewall!

There are still some manual steps to be taken (which I'd like to automate in due course). These are the fairly standard things that you do when starting any Django project, plus an extra step for bootstrapping PostGIS.

Create your database

From the command line, you'll need to create the database for you application. You need to specify the PostGIS template, so use something like:

$ bin/createdb -T template_postgis <db name>

Change the settings for your application

Edit the settings.py for your application, and make sure that you're using 'postgresql_psycopg2' as the database engine. Set the database name as appropriate for your application. You should also add 'django.contrib.gis' to your INSTALLED_APPS setting, and you'll also need to add the following two lines to your settings.py:

GDAL_LIBRARY_PATH = '/path/to/buildout/parts/gdal/lib/libgdal.dylib'
GEOS_LIBRARY_PATH = '/path/to/buildout/parts/geos/lib/libgeos_c.dylib'

Add Google projection

I'll confess: I'm only doing this because the GeoDjango docs say you should! I don't know enough about GeoDjango yet to understand why. But you should do the following:

$ bin/django shell
>>> from django.contrib.gis.utils import add_postgis_srs
>>> add_postgis_srs(900913)
>>> ^D
$

If you get an error when importing add_postgis_srs, then double check you got the GDAL_LIBRARY_PATH and GEOS_LIBRARY_PATH correct, and that the files specified were built. (I'm on Mac OS X - I suspect the exact file name may change depending on platform.)

Done!

Once all that's done, you should hopefully be able to bin/django syncdb, start a new app (using fez.djangoskel, of course!) and start using GeoDjango.

I shall refine the above process over time (in particular, there are some modifications I'd like to make to djangorecipe to remove the manual steps at the end), and I'll post extra parts when I've done that.

 

Comments

1 Ben Ford says...

Have a look at z3c.recipe.filetemplate and a customization of it twodeg.recipe.apacheconf, to help with the extra manual steps and for building an apache virtualhost file. What's the rationale for using different cmmi recipies, did you have problems with one?

Great write up! Ben

Posted at 1:26 p.m. on April 17, 2009

2 Dan Fairs says...

Ben - I think I based the [postgis] section on another buildout I'd seen. There isn't really a reason to use two, the regular zc.recipe.cmmi would probably do fine. When I get a moment I'll double-check and update the post. Thanks!

Posted at 5:57 p.m. on April 17, 2009

3 kiorky says...

Hello,

Let me introduce to you minitage (http://www.minitage.org). Indeed, I think you can find it somewhat useful for your needs.

One success story around GeoDjango can be: http://www.bisonvert.net/

Minitage is a meta package manager, a long word to say that it will wraps a lot of specialized buildouts to arrange your project dependencies, and even your project in a well known layout. To help you using what's in your minitage, you have some custom buildout recipes ( see minitage.recipe) to integrate "minitage dependencies" automaticly in your environment at installation time.

Specificly to django, minitage.paste contains a specific django paster template which has some cool features like geodjango support and WSGI configuration and integration with dj.paste, another paster application factory.

Posted at 7:25 p.m. on April 23, 2009

4 James Bellinger says...

Your e-mail send link fails with "{exception}", so I'll post my question here...

Is there any reason your adaptation DLL has SimpleLookup as a separate class? From what I can see, it accesses internal structures, so it's not possible to implement any other kind of lookup. Any reason you didn't just stick the adaptation function on Registry itself? (also, for using namespaces it'd be nice if it were named AdapterRegistry or at least something less general than Registry, but no big deal there)

Posted at 9:10 p.m. on June 16, 2009

I've disabled comments for now due to spam problems - I'll turn them back on when I've fixed it!

This won't be published anywhere, it's just in case I need to contact you.

You can use Markdown in your comments. Be sensible!

Sorry about this, but I don't want spam comments.