Wednesday, June 4, 2008

GeoDjango on Slicehost: Creating a GeoDjango Project (4 of 4)


This final post goes over how to create a test GeoDjango project.

Creating a Website Directory Structure


Create a location for the website directory structures.
mkdir ~/website

Create a directory structure for the test_geodjango.slicename.com website.
mkdir -p ~/website/test_geodjango.slicename.com/{public,private,log,cgi-bin,backup}

Create a GeoDjango Project


Create a default Django project...
cd ~/website/test_geodjango.slicename.com/public
django-admin.py startproject test_geodjango

Add the GDAL library path to the Django project settings...
nano ~/website/test_geodjango.slicename.com/public/test_geodjango/settings.py

Add the following line so your Django project can found the GDAL library...
GDAL_LIBRARY_PATH = '/usr/local/lib/libgdal.so'

Test out the project (using the internal web server)...
python ~/website/test_geodjango.slicename.com/public/test_geodjango/manage.py runserver 8001

You should see a response like the following...
Validating models... 0 errors found Django version 0.97-pre-SVN-7547, using settings 'test_geodjango.settings' Development server is running at http://127.0.0.1:8001/ Quit the server with CONTROL-C.

Even though the server is running, you would be able to see a Django page since port 8001 is not open. Quit the server for now...

Create a new view


Create a new view file for the project...
nano ~/website/test_geodjango.slicename.com/public/test_geodjango/views.py

and insert the following code
from django.http import HttpResponse
import datetime

def current_datetime(request):
now = datetime.datetime.now()
html = "It is now %s." % now
return HttpResponse(html)

Edit the URL configuration file
nano ~/website/test_geodjango.slicename.com/public/test_geodjango/urls.py

Replace the content with the following code which will be used to display a Django test page...
from django.conf.urls.defaults import *
from test_geodjango.views import current_datetime

urlpatterns = patterns('',
(r'^time/$', current_datetime),
)

Configure Apache to recognize the new virtual host
sudo nano /etc/apache2/sites-available/test_geodjango.slicename.com

Add the following to configure the virtual host
# Place any notes or comments you have here
# It will make any customization easier to understand in the weeks to come

# domain: test_geodjango.domain.com
# public: /home/demo/website/test_geodjango.domain.com/


# Admin email, Server Name (domain name) and any aliases
ServerAdmin webmaster@slicename.com
ServerName test_geodjango.slicename.com

# Index file and Document Root (where the public files are located)
#DirectoryIndex index.html
DocumentRoot /home/demo/website/test_geodjango.slicename.com/public


Order deny,allow
Allow from all



SetHandler python-program
PythonPath "['/home/demo/website/test_geodjango.slicename.com/public'] + sys.path"
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE test_geodjango.settings
PythonDebug On


# Custom log file locations
LogLevel warn
ErrorLog /home/demo/website/test_geodjango.slicename.com/log/error.log
CustomLog /home/demo/website/test_geodjango.slicename.com/log/access.log combined


Enable the site and reload apache to use the new configuration...
sudo a2ensite test_geodjango.slicename.com
sudo /etc/init.d/apache2 reload
sudo apache2ctl graceful

On your local computer, edit the /etc/hosts file and add the following line to setup an override
11.222.333.444 test_geodjango.slicename.com

Test it out, by opening up a Web browser and go to http://test_geodjango.slicename.com/time/ You should see a page that shows something like...
It is now 2008-05-24 11:22:33.991752.

Create a PostGIS database


Next we will create a PostGIS database for the project... (I have included the shell prompts to make it more clear what user/context is running the command.)
myslice ~: sudo su - postgres
postgres@myslice:~$ createuser -SDRP testuser
postgres@myslice:~$ createdb -O testuser test_geodjango_db
postgres@myslice:~$ createlang plpgsql test_geodjango_db
postgres@myslice:~$ psql -d test_geodjango_db -f /usr/share/lwpostgis.sql
postgres@myslice:~$ psql -d test_geodjango_db -f /usr/share/spatial_ref_sys.sql
postgres@myslice:~$ psql test_geodjango_db
test_geodjango_db=# ALTER TABLE geometry_columns OWNER TO testuser;
test_geodjango_db=# ALTER TABLE spatial_ref_sys OWNER TO testuser;
test_geodjango_db=# \q
postgres@myslice:~$ exit
myslice ~:

Configure the Django database configuration


(reference: http://www.djangobook.com/en/1.0/chapter05/)
Edit the settings file for the Django project...
nano  ~/website/test_geodjango.slicename.com/public/test_geodjango/settings.py

And update the database connection parameters
DATABASE_ENGINE = 'postgresql_psycopg2'
DATABASE_NAME = 'test_geodjango_db'
DATABASE_USER = 'testuser'
DATABASE_PASSWORD = 'password'
DATABASE_HOST = ''
DATABASE_PORT = ''

Test the database connection


Open up a Python shell for the project...
cd ~/website/test_geodjango.slicename.com/public/test_geodjango
python manage.py shell

Python 2.5.2 (r252:60911, Apr 21 2008, 11:17:30)
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

>>> from django.db import connection
>>> cursor = connection.cursor()
>>>

If the cursor = connection.cursor() command did not produce any response, then the database connection was successfully made.

Add a Django App and Define a Model


(see http://www.djangobook.com/en/1.0/chapter05/ and http://code.djangoproject.com/wiki/GeoDjango)
Create a Django application and edit the model configuration file...
python manage.py startapp testapp
nano testapp/models.py

And replace with the following...
from django.contrib.gis.db import models

class District(models.Model):
name = models.CharField(max_length=35)
num  = models.IntegerField()
poly = models.PolygonField()
objects = models.GeoManager()

class School(models.Model):
name  = models.CharField(max_length=35)
point = models.PointField()
objects = models.GeoManager()

Install the Django App


Edit the settings configuration file...
nano settings.py

and edit the INSTALLED_APPS section as follows
INSTALLED_APPS = (
#'django.contrib.auth',
#'django.contrib.contenttypes',
#'django.contrib.sessions',
#'django.contrib.sites',
'test_geodjango.testapp',
)

Sync the database with the Django model...
python manage.py syncdb

which should produce the following...
Creating table testapp_school
Creating table testapp_district
Installing custom SQL for testapp.School model
Installing custom SQL for testapp.District model

Test access to the database from the command line...
python manage.py shell
>>> from testapp.models import District, School
>>> d1 = District(name='Test District 1' , num=1, poly='POLYGON((-96 29,-95 29,-95 30,-96 29))' )
>>> d1.save()
>>> qs1 = District.objects.filter(poly__bbcontains='POINT(-95.362293 29.756539)')
>>> qs1

Python should echo back a District object. This returns an array with a single district record, since the district polygon's bounding box contains the point.
[]

Try again a query that does not return any points (since the point is not contained within the district polygon)...
>>> qs2 = District.objects.filter(poly__contains='POINT(-95.362293 29.756539)')
>>> qs2

[]

Displaying GeoDjango Results on a Web Page


Create another view file for the project...
nano ~/website/test_geodjango.slicename.com/public/test_geodjango/testapp/views.py

and add a view that returns the results of a GeoDjango query...
from django.http import HttpResponse
import datetime
from models import District, School

def test_geodjango_view(request):
now = datetime.datetime.now()
pointWkt = 'POINT(-95.362293 29.056539)'
districtSet = District.objects.filter(poly__contains=pointWkt)
html = "It is now %s." % now
html += "

"
if len(districtSet)>0:
for district in districtSet:
html += "%s is in %s" % (pointWkt, district.name)
else:
html += "%s is not within any districts" % pointWkt
return HttpResponse(html)

Update the URL configuration...
nano ~/website/test_geodjango.slicename.com/public/test_geodjango/urls.py

to match the following...
from django.conf.urls.defaults import *
from test_geodjango.views import current_datetime
from test_geodjango.testapp.views import test_geodjango_view

urlpatterns = patterns('',
(r'^time/$', current_datetime),
(r'^test/$', test_geodjango_view),
)

Reload the Apache configuration...
sudo /etc/init.d/apache2 reload
sudo apache2ctl graceful

If you get a message saying that httpd is not running, try reloading the Apache configuration again...
sudo /etc/init.d/apache2 reload
sudo apache2ctl graceful

Test out the web page...


Point a browser at: http://test_geodjango.slicename.com/test/
You should see something similar to
It is now 2008-06-04 21:26:17.022444.

POINT(-95.362293 29.056539) is in Test District 1

if that works, you now have a working (although trivial) GeoDjango website served via Apache. Now its up to you to make do something interesting. Good luck...

Saturday, May 17, 2008

Quick camping trip to Pinckney

Last night we threw the camping stuff and the dog in the car and headed out to Pinckney State Park to get back to nature (in a state-owned and managed sense).

Eddy seemed to enjoy the trip, and was proud of successfully defending the campsite from the local raccoon.



View Larger Map

Friday, August 24, 2007

Milolii Beach, Na Pali Coast

Description: A two stall composting groover.

Story: This fine specimen is located on Milolii Beach, which is only accessible by boat. Anna and I visited it while on a sea kayaking trip along the Na Pali coast.

Milolii Beach Outhouse

Location: Milolii Beach, Na Pali Coast State Park, Kauai, Hawaii


Photo Credit: Tyler

Thursday, January 23, 2003

Fowler-Hilliard Hut Outhouse

Description: Double stall with the classic sliver moon on the door. This is a classic outhouse with the gore range present in the background. This outhouse sits on top of a ridge with incredible skiing right off the pot.

Fowler-Hillaird Hut OuthouseFowler-Hilliard Hut Outhouse

Photo Credits: Brad, Beth

Location: Fowler-Hilliard Hut, 10th Mountain Hut System, Colorado