1
0
mirror of https://github.com/django/django.git synced 2025-07-04 09:49:12 +00:00

gis: added spatial database creation utility and fixed a bug in gdal geomtype module.

git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@5761 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2007-07-26 02:00:38 +00:00
parent 1c2a08d2d7
commit df45fba3ea
3 changed files with 192 additions and 0 deletions

View File

@ -1,4 +1,5 @@
from types import StringType from types import StringType
from django.contrib.gis.gdal.error import OGRException
#### OGRGeomType #### #### OGRGeomType ####
class OGRGeomType(object): class OGRGeomType(object):

View File

@ -1,2 +1,3 @@
from LayerMapping import LayerMapping from LayerMapping import LayerMapping
from inspect_data import sample from inspect_data import sample
from spatial_db import create_spatial_db

View File

@ -0,0 +1,190 @@
from django.conf import settings
from django.core.management import syncdb
from django.db import connection, backend
from django.test.utils import _set_autocommit, TEST_DATABASE_PREFIX
from commands import getstatusoutput
import os, re, sys
def create_lang(db_name, verbosity=1):
"This sets up the pl/pgsql language on the given database."
# Getting the command-line options for the shell command
options = get_cmd_options(db_name)
# Constructing the 'createlang' command.
createlang_cmd = 'createlang %splpgsql' % options
if verbosity >= 1: print createlang_cmd
# Must have database super-user privileges to execute createlang -- it must
# also be in your path.
status, output = getstatusoutput(createlang_cmd)
# Checking the status of the command, 0 => execution successful
if status != 0:
raise Exception, "Error executing 'plpgsql' command: %s\n" % output
def _create_with_cursor(db_name, verbosity=1, autoclobber=False):
"Creates database with psycopg2 cursor."
# Constructing the necessary SQL to create the database (the DATABASE_USER
# must possess the privileges to create a database)
create_sql = 'CREATE DATABASE %s OWNER %s' % (backend.quote_name(db_name),
settings.DATABASE_USER)
cursor = connection.cursor()
_set_autocommit(connection)
try:
# Trying to create the database first.
cursor.execute(create_sql)
except Exception, e:
# Drop and recreate, if necessary.
if not autoclobber:
confirm = raw_input("\nIt appears the database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % db_name)
if autoclobber or confirm == 'yes':
if verbosity >= 1: print 'Destroying old spatial database...'
drop_db(db_name)
if verbosity >= 1: print 'Creating new spatial database...'
cursor.execute(create_sql)
else:
raise Exception, 'Spatial Database Creation canceled.'
created_regex = re.compile(r'^createdb: database creation failed: ERROR: database ".+" already exists')
def _create_with_shell(db_name, verbosity=1, autoclobber=False):
"""If no spatial database already exists, then using a cursor will not work. Thus, a
`createdb` command will be issued through the shell to bootstrap the database."""
# Getting the command-line options for the shell command
options = get_cmd_options(False)
create_cmd = 'createdb -O %s %s%s' % (settings.DATABASE_USER, options, db_name)
if verbosity >= 1: print create_cmd
# Attempting to create the database.
status, output = getstatusoutput(create_cmd)
if status != 0:
if created_regex.match(output):
if not autoclobber:
confirm = raw_input("\nIt appears the database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % db_name)
if autoclobber or confirm == 'yes':
if verbosity >= 1: print 'Destroying old spatial database...'
drop_cmd = 'dropdb %s%s' % (options, db_name)
status, output = getstatusoutput(drop_cmd)
if status != 0:
raise Exception, 'Could not drop database %s: %s' % (db_name, output)
if verbosity >= 1: print 'Creating new spatial database...'
status, output = getstatusoutput(create_cmd)
if status != 0:
raise Exception, 'Could not create database after dropping: %s' % output
else:
raise Exception, 'Spatial Database Creation canceled.'
else:
raise Exception, 'Unknown error occurred in creating database: %s' % output
def create_spatial_db(test=False, verbosity=1, autoclobber=False):
"This Python routine creates a spatial database based on settings.py."
# Making sure we're using PostgreSQL and psycopg2
if settings.DATABASE_ENGINE != 'postgresql_psycopg2':
raise Exception, 'Spatial database creation only supported postgresql_psycopg2 platform.'
# This routine depends on getstatusoutput(), which does not work on Windows.
# TODO: Consider executing shell commands with popen for Windows compatibility
if os.name == 'nt':
raise Exception, 'Automatic spatial database creation only supported on *NIX platforms.'
# Getting the spatial database name
if test:
db_name = get_spatial_db(test=True)
_create_with_cursor(db_name, verbosity=verbosity, autoclobber=autoclobber)
else:
db_name = get_spatial_db()
_create_with_shell(db_name, verbosity=verbosity, autoclobber=autoclobber)
# Creating the db language.
create_lang(db_name, verbosity=verbosity)
# Now adding in the PostGIS routines.
load_postgis_sql(db_name, verbosity=verbosity)
if verbosity >= 1: print 'Creation of spatial database %s successful.' % db_name
# Closing the connection
connection.close()
settings.DATABASE_NAME = db_name
# Syncing the database
syncdb(verbosity, interactive=False)
# Get a cursor (even though we don't need one yet). This has
# the side effect of initializing the test database.
cursor = connection.cursor()
def drop_db(db_name=False, test=False):
"Using the cursor, drops the given database. All exceptions will be propagated up."
if not db_name: db_name = get_spatial_db(test=test)
cursor = connection.cursor()
cursor.execute("DROP DATABASE %s" % backend.quote_name(db_name))
def get_cmd_options(db_name):
"Obtains the command-line PostgreSQL connection options for shell commands."
# The db_name parameter is optional
if db_name:
options = '-d %s -U %s ' % (db_name, settings.DATABASE_USER)
else:
options = '-U %s ' % settings.DATABASE_USER
if settings.DATABASE_HOST:
options += '-h %s ' % settings.DATABASE_HOST
if settings.DATABASE_PORT:
options += '-p %s ' % settings.DATABASE_PORT
return options
def get_spatial_db(test=False):
"""This routine returns the name of the spatial database.
Set the 'test' keyword for the test spatial database name."""
if test:
if settings.TEST_DATABASE_NAME:
test_db_name = settings.TEST_DATABASE_NAME
else:
test_db_name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME
return test_db_name
else:
if not settings.DATABASE_NAME:
raise Exception, 'must configure DATABASE_NAME in settings.py'
return settings.DATABASE_NAME
def load_postgis_sql(db_name, verbosity=1):
"This routine loads up the PostGIS SQL files lwpostgis.sql and spatial_ref_sys.sql."
# Getting the path to the PostGIS SQL
try:
# POSTGIS_SQL_PATH may be placed in settings to tell GeoDjango where the
# PostGIS SQL files are located
sql_path = settings.POSTGIS_SQL_PATH
except AttributeError:
sql_path = '/usr/local/share'
# The PostGIS SQL post-creation files.
lwpostgis_file = os.path.join(sql_path, 'lwpostgis.sql')
srefsys_file = os.path.join(sql_path, 'spatial_ref_sys.sql')
if not os.path.isfile(lwpostgis_file):
raise Exception, 'Could not find PostGIS function definitions in %s' % lwpostgis_file
if not os.path.isfile(srefsys_file):
raise Exception, 'Could not find PostGIS spatial reference system definitions in %s' % srefsys_file
# Getting the psql command-line options.
options = get_cmd_options(db_name)
# Now trying to load up the PostGIS functions
cmd = 'psql %s-f %s' % (options, lwpostgis_file)
if verbosity >= 1: print cmd
status, output = getstatusoutput(cmd)
if status != 0:
raise Exception, 'Error in loading PostGIS lwgeometry routines.'
# Now trying to load up the Spatial Reference System table
cmd = 'psql %s-f %s' % (options, srefsys_file)
if verbosity >= 1: print cmd
status, output = getstatusoutput(cmd)
if status !=0:
raise Exception, 'Error in loading PostGIS spatial_ref_sys table.'