Index: docs/index.txt
===================================================================
--- docs/index.txt	(revision 12454)
+++ docs/index.txt	(working copy)
@@ -168,6 +168,7 @@
     * :ref:`Databrowse <ref-contrib-databrowse>`
     * :ref:`E-mail (sending) <topics-email>`
     * :ref:`Flatpages <ref-contrib-flatpages>`
+    * :ref:`GeoDjango <ref-contrib-gis>`
     * :ref:`Humanize <ref-contrib-humanize>`
     * :ref:`Internationalization <topics-i18n>`
     * :ref:`Jython support <howto-jython>`
Index: docs/ref/contrib/gis/create_template_postgis-1.4.sh
===================================================================
--- docs/ref/contrib/gis/create_template_postgis-1.4.sh	(revision 0)
+++ docs/ref/contrib/gis/create_template_postgis-1.4.sh	(revision 0)
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib
+createdb -E UTF8 template_postgis # Create the template spatial database.
+createlang -d template_postgis plpgsql # Adding PLPGSQL language support.
+psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';"
+psql -d template_postgis -f $POSTGIS_SQL_PATH/postgis.sql # Loading the PostGIS SQL routines
+psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql
+psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables.
+psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"

Property changes on: docs/ref/contrib/gis/create_template_postgis-1.4.sh
___________________________________________________________________
Name: svn:executable
   + *

Index: docs/ref/contrib/gis/measure.txt
===================================================================
--- docs/ref/contrib/gis/measure.txt	(revision 0)
+++ docs/ref/contrib/gis/measure.txt	(revision 0)
@@ -0,0 +1,103 @@
+=================================================
+Measurement Units API (``Distance`` and ``Area``)
+=================================================
+
+The `measure module`__ allows for convenient representation of distance and 
+area units of measure. [#]_ The module contains two objects, ``Distance``
+and ``Area`` -- both of which may be accessed via the ``D`` and ``A`` aliases, 
+respectively.
+
+__ http://code.djangoproject.com/browser/django/branches/gis/django/contrib/gis/measure.py
+
+The ``Distance`` and ``Area`` Objects
+=====================================
+
+``Distance`` objects may be instantiated using a keyword argument indicating the 
+context of the units.  In the example below, two different distance objects are 
+instantiated in units of kilometers (``km``) and miles (``mi``)::
+
+    >>> from django.contrib.gis.measure import Distance, D
+    >>> d1 = Distance(km=5)
+    >>> print d1
+    5.0 km
+    >>> d2 = D(mi=5) # `D` is an alias for `Distance`
+    >>> print d2
+    5.0 mi
+
+Conversions are easy, just access the preferred unit attribute name to get a
+converted distance quantity::
+
+   >>> print d1.mi # Converting 5 kilometers to miles
+   3.10685596119
+   >>> print d2.km # Converting 5 miles to kilometers
+   8.04672
+
+Moreover, arithmetic operations may be performed between the distance
+objects::
+
+    >>> print d1 + d2 # Adding 5 miles to 5 kilometers
+    13.04672 km    
+    >>> print d2 - d1 # Subtracting 5 kilometers from 5 miles
+    1.89314403881 mi
+
+Two ``Distance`` objects multiplied together will yield an ``Area`` object,
+which uses squared units of measure::
+
+    >>> a = d1 * d2 # Returns an Area object.
+    >>> print a
+    40.2336 sq_km
+
+To determine what the attribute abbreviation of a unit is, the ``unit_attname``
+class method may be used:
+
+    >>> print Distance.unit_attname('US Survey Foot')
+    survey_ft
+    >>> print Distance.unit_attname('centimeter')
+    cm
+
+Supported units
+===============
+
+=================================  ========================================
+Unit Attribute                     Full name or alias(es)
+=================================  ========================================
+``km``                             Kilometre, Kilometer   
+``mi``                             Mile
+``m``                              Meter, Metre
+``yd``                             Yard
+``ft``                             Foot, Foot (International)
+``survey_ft``                      U.S. Foot, US survey foot
+``inch``                           Inches
+``cm``                             Centimeter
+``mm``                             Millimetre, Millimeter
+``um``                             Micrometer, Micrometre
+``british_ft``                     British foot (Sears 1922)
+``british_yd``                     British yard (Sears 1922)
+``british_chain_sears``            British chain (Sears 1922)
+``indian_yd``                      Indian yard, Yard (Indian)
+``sears_yd``                       Yard (Sears)
+``clarke_ft``                      Clarke's Foot
+``chain``                          Chain
+``chain_benoit``                   Chain (Benoit)
+``chain_sears``                    Chain (Sears)
+``british_chain_benoit``           British chain (Benoit 1895 B)
+``british_chain_sears_truncated``  British chain (Sears 1922 truncated)
+``gold_coast_ft``                  Gold Coast foot
+``link``                           Link
+``link_benoit``                    Link (Benoit)
+``link_sears``                     Link (Sears)
+``clarke_link``                    Clarke's link
+``fathom``                         Fathom
+``rod``                            Rod
+``nm``                             Nautical Mile
+``nm_uk``                          Nautical Mile (UK)
+``german_m``                       German legal metre
+=================================  ========================================
+
+``Area`` attributes are the same as ``Distance`` attributes, except they are 
+prefixed with ``sq_`` (area units are square in nature).
+
+.. rubric:: Footnotes
+.. [#] `Robert Coup <http://koordinates.com/>`_ is the initial author of the measure objects, 
+       and was inspired by Brian Beck's work in `geopy <http://exogen.case.edu/projects/geopy/>`_ 
+       and Geoff Biggs' PhD work on dimensioned units for robotics.
Index: docs/ref/contrib/gis/tutorial.txt
===================================================================
--- docs/ref/contrib/gis/tutorial.txt	(revision 0)
+++ docs/ref/contrib/gis/tutorial.txt	(revision 0)
@@ -0,0 +1,746 @@
+==================
+GeoDjango Tutorial
+==================
+
+Introduction
+============
+
+GeoDjango is an add-on for Django that turns it into a world-class geographic
+web framework.  GeoDjango strives to make at as simple as possible to create
+geographic web applications, like location-based services.  Some features include:
+
+* Django model fields for `OGC`_ geometries, that may be edited in the admin.
+* Extensions to Django's ORM for the querying and manipulation of spatial data.
+* Loosely-coupled, high-level Python interfaces for GIS geometry operations and
+  data formats.
+
+This tutorial assumes a familiarity with Django; thus, if you're brand new to 
+Django please read through the `regular tutorial`__ to introduce yourself with 
+Django concepts.  GeoDjango has special prerequisites over what is required by Django -- 
+please consult the `GeoDjango installation documentation`_ for more details.
+
+This tutorial is going to guide you through guide the user through the creation
+of a geographic web application for viewing the `world borders`_. [#]_  Some of
+the code used in this tutorial is taken from and/or inspired by the 
+`GeoDjango basic apps`_ project. [#]_
+
+.. note:
+
+    Proceed through the tutorial sections sequentially for step-by-step 
+    instructions.
+
+
+.. _OGC: http://www.opengeospatial.org/
+.. _GeoDjango installation documentation: install.html
+.. _world borders: http://thematicmapping.org/downloads/world_borders.php
+.. _GeoDjango basic apps: http://code.google.com/p/geodjango-basic-apps/
+
+__ http://docs.djangoproject.com/en/dev/intro/tutorial01/#intro-tutorial01
+
+Setting Up
+==========
+
+Create a Spatial Database
+-------------------------
+
+.. note::
+
+    MySQL and Oracle users can skip this section because spatial types
+    are already built into the database.
+
+First, a spatial database needs to be created for our project.  If using
+PostgreSQL and PostGIS, then the following commands will 
+create the database from a `spatial database template`_::
+
+    $ createdb -T template_postgis geodjango
+    
+.. note::
+
+    This command must be issued by a database user that has permissions to
+    create a database.  Here is an example set of commands to create such
+    a user::
+
+        $ sudo su - postgres
+        $ createuser --createdb geo
+        $ exit
+    
+    Replace ``geo`` to correspond to the system login user name will be
+    connecting to the database.  For example, ``johndoe`` if that is the 
+    system user that will be running GeoDjango.
+
+Users of SQLite and SpatiaLite should consult the instructions on how
+to create a `SpatiaLite database`_.
+
+.. _spatial database template: install.html#spatialdb-template
+.. _spatialite database: install.html#creating-a-spatial-database-for-spatialite
+
+Create GeoDjango Project
+------------------------
+
+Use the ``django-admin.py`` script like normal to create a ``geodjango`` project::
+
+    $ django-admin.py startproject geodjango
+
+With the project initialized, now create a ``world`` Django application within
+the ``geodjango`` project::
+
+    $ cd geodjango
+    $ python manage.py startapp world
+
+Configure ``settings.py``
+-------------------------
+
+The ``geodjango`` project settings are stored in the ``settings.py`` file.  Edit
+the database connection settings appropriately::
+
+    DATABASE_ENGINE = 'postgresql_psycopg2'
+    DATABASE_NAME = 'geodjango'
+    DATABASE_USER = 'geo'
+
+In addition, modify the ``INSTALLED_APPS`` setting to include ``django.contrib.admin``,
+``django.contrib.gis``, and ``geodjango.world`` (our newly created application)::
+
+    INSTALLED_APPS = (
+        'django.contrib.auth',
+        'django.contrib.contenttypes',
+        'django.contrib.sessions',
+        'django.contrib.sites',
+        'django.contrib.admin',
+        'django.contrib.gis',
+        'geodjango.world'
+    )
+
+Geographic Data
+===============
+
+
+.. _worldborders:
+
+World Borders
+-------------
+
+The world borders data is available in this `zip file`__.  Create a data directory
+in the ``world`` application, download the world borders data, and unzip::
+
+    $ mkdir world/data
+    $ cd world/data
+    $ wget http://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip
+    $ unzip TM_WORLD_BORDERS-0.3.zip
+    $ cd ../..
+
+The world borders ZIP file contains a set of data files collectively known as
+an `ESRI Shapefile`__, one of the most popular geospatial data formats.  When
+unzipped the world borders data set includes files with the following extensions:
+
+* ``.shp``: Holds the vector data for the world borders geometries.
+* ``.shx``: Spatial index file for geometries stored in the ``.shp``.
+* ``.dbf``: Database file for holding non-geometric attribute data 
+  (e.g., integer and character fields). 
+* ``.prj``: Contains the spatial reference information for the geographic
+  data stored in the shapefile.
+
+__ http://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip
+__ http://en.wikipedia.org/wiki/Shapefile
+
+Use ``ogrinfo`` to examine spatial data
+---------------------------------------
+
+The GDAL ``ogrinfo`` utility is excellent for examining metadata about 
+shapefiles (or other vector data sources)::
+
+    $ ogrinfo world/data/TM_WORLD_BORDERS-0.3.shp
+    INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
+          using driver `ESRI Shapefile' successful.
+    1: TM_WORLD_BORDERS-0.3 (Polygon)
+
+Here ``ogrinfo`` is telling us that the shapefile has one layer, and that
+layer contains polygon data.  To find out more we'll specify the layer name
+and use the ``-so`` option to get only important summary information::
+
+    $ ogrinfo -so world/data/TM_WORLD_BORDERS-0.3.shp TM_WORLD_BORDERS-0.3
+    INFO: Open of `world/data/TM_WORLD_BORDERS-0.3.shp'
+          using driver `ESRI Shapefile' successful.
+
+    Layer name: TM_WORLD_BORDERS-0.3
+    Geometry: Polygon
+    Feature Count: 246
+    Extent: (-180.000000, -90.000000) - (180.000000, 83.623596)
+    Layer SRS WKT:
+    GEOGCS["GCS_WGS_1984",
+        DATUM["WGS_1984",
+            SPHEROID["WGS_1984",6378137.0,298.257223563]],
+        PRIMEM["Greenwich",0.0],
+        UNIT["Degree",0.0174532925199433]]
+    FIPS: String (2.0)
+    ISO2: String (2.0)
+    ISO3: String (3.0)
+    UN: Integer (3.0)
+    NAME: String (50.0)
+    AREA: Integer (7.0)
+    POP2005: Integer (10.0)
+    REGION: Integer (3.0)
+    SUBREGION: Integer (3.0)
+    LON: Real (8.3)
+    LAT: Real (7.3)
+
+This detailed summary information tells us the number of features in the layer
+(246), the geographical extent, the spatial reference system ("SRS WKT"), 
+as well as detailed information for each attribute field.  For example,
+``FIPS: String (2.0)`` indicates that there's a ``FIPS`` character field
+with a maximum length of 2; similarly, ``LON: Real (8.3)`` is a floating-point
+field that holds a maximum of 8 digits up to three decimal places.  Although
+this information may be found right on the `world borders`_ website, this shows
+you how to determine this information yourself when such metadata is not 
+provided.
+
+Geographic Models
+=================
+
+Defining a Geographic Model
+---------------------------
+
+Now that we've examined our world borders data set using ``ogrinfo``, we can
+create a GeoDjango model to represent this data::
+
+    from django.contrib.gis.db import models
+
+    class WorldBorders(models.Model):
+        # Regular Django fields corresponding to the attributes in the 
+	# world borders shapefile.
+        name = models.CharField(max_length=50)
+        area = models.IntegerField()
+        pop2005 = models.IntegerField('Population 2005')
+        fips = models.CharField('FIPS Code', max_length=2)
+        iso2 = models.CharField('2 Digit ISO', max_length=2)
+        iso3 = models.CharField('3 Digit ISO', max_length=3)
+        un = models.IntegerField('United Nations Code')
+        region = models.IntegerField('Region Code')
+        subregion = models.IntegerField('Sub-Region Code')
+    	lon = models.FloatField()
+    	lat = models.FloatField()
+
+	# GeoDjango-specific: a geometry field (MultiPolygonField), and 
+        # overriding the default manager with a GeoManager instance.
+	mpoly = models.MultiPolygonField()
+	objects = models.GeoManager()
+
+        # So the model is pluralized correctly in the admin.
+        class Meta:
+            verbose_name_plural = "World Borders"
+ 
+        # Returns the string representation of the model.       
+        def __unicode__(self):
+            return self.name
+
+Two important things to note:
+
+1. The ``models`` module is imported from ``django.contrib.gis.db``.
+2. The model overrides its default manager with ``GeoManager``; this is *required*
+   to perform spatial queries.  
+
+When declaring a geometry field on your model the default spatial reference system
+is WGS84 (meaning the `SRID`__ is 4326) -- in other words, the field coordinates are in
+longitude/latitude pairs in units of degrees.  If you want the coordinate system to be
+different, then SRID of the geometry field may be customized by setting the ``srid``
+with an integer corresponding to the coordinate system of your choice. 
+
+__ http://en.wikipedia.org/wiki/SRID
+
+Run ``syncdb``
+--------------
+
+After you've defined your model, it needs to be synced with the spatial database.
+First, let's look at the SQL that will generate the table for the ``WorldBorders`` 
+model::
+
+    $ python manage.py sqlall world
+
+This management command should produce the following output::
+
+    BEGIN;
+    CREATE TABLE "world_worldborders" (
+        "id" serial NOT NULL PRIMARY KEY,
+        "name" varchar(50) NOT NULL,
+        "area" integer NOT NULL,
+        "pop2005" integer NOT NULL,
+        "fips" varchar(2) NOT NULL,
+        "iso2" varchar(2) NOT NULL,
+        "iso3" varchar(3) NOT NULL,
+        "un" integer NOT NULL,
+        "region" integer NOT NULL,
+        "subregion" integer NOT NULL,
+        "lon" double precision NOT NULL,
+        "lat" double precision NOT NULL
+    )
+    ;
+    SELECT AddGeometryColumn('world_worldborders', 'mpoly', 4326, 'MULTIPOLYGON', 2);
+    ALTER TABLE "world_worldborders" ALTER "mpoly" SET NOT NULL;
+    CREATE INDEX "world_worldborders_mpoly_id" ON "world_worldborders" USING GIST ( "mpoly" GIST_GEOMETRY_OPS );
+    COMMIT;
+
+If satisfied, you may then create this table in the database by running the
+``syncdb`` management command::
+
+    $ python manage.py syncdb
+    Creating table world_worldborders
+    Installing custom SQL for world.WorldBorders model
+
+The ``syncdb`` command may also prompt you to create an admin user; go ahead and
+do so (not required now, may be done at any point in the future using the 
+``createsuperuser`` management command).
+
+Importing Spatial Data
+======================
+
+This section will show you how to take the data from the world borders
+shapefile and import it into GeoDjango models using the `LayerMapping`_
+utility.  There are many different different ways to import data in to a 
+spatial database -- besides the tools included within GeoDjango, you
+may also use the following to populate your spatial database:
+
+* `ogr2ogr`_: Command-line utility, included with GDAL, that 
+  supports loading a multitude of vector data formats into
+  the PostGIS, MySQL, and Oracle spatial databases.
+* `shp2pgsql`_: This utility is included with PostGIS and only supports
+  ESRI shapefiles.
+
+.. _LayerMapping: layermapping.html
+.. _ogr2ogr: http://www.gdal.org/ogr/ogr2ogr.html
+.. _shp2pgsql: http://postgis.refractions.net/documentation/manual-1.3/ch04.html#id2571948
+
+.. _gdalinterface:
+
+GDAL Interface
+--------------
+
+Earlier we used the the ``ogrinfo`` to explore the contents of the world borders
+shapefile.  Included within GeoDjango is an interface to GDAL's powerful OGR
+library -- in other words, you'll be able explore all the vector data sources
+that OGR supports via a Pythonic API.
+
+First, invoke the Django shell::
+
+    $ python manage.py shell
+
+If the :ref:`worldborders` data was downloaded like earlier in the
+tutorial, then we can determine the path using Python's built-in
+``os`` module::
+
+    >>> import os
+    >>> from geodjango import world
+    >>> world_shp = os.path.abspath(os.path.join(os.path.dirname(world.__file__),
+    ...                             'data/TM_WORLD_BORDERS-0.3.shp'))
+
+Now, the world borders shapefile may be opened using GeoDjango's 
+``DataSource`` interface::
+
+    >>> from django.contrib.gis.gdal import *
+    >>> ds = DataSource(world_shp)
+    >>> print ds
+    / ... /geodjango/world/data/TM_WORLD_BORDERS-0.3.shp (ESRI Shapefile)
+
+Data source objects can have different layers of geospatial features; however, 
+shapefiles are only allowed to have one layer::
+
+    >>> print len(ds)
+    1
+    >>> lyr = ds[0]
+    >>> print lyr
+    TM_WORLD_BORDERS-0.3
+
+You can see what the geometry type of the layer is and how many features it
+contains::
+
+    >>> print lyr.geom_type
+    Polygon
+    >>> print len(lyr)
+    246
+
+.. note::
+
+    Unfortunately the shapefile data format does not allow for greater
+    specificity with regards to geometry types.  This shapefile, like 
+    many others, actually includes ``MultiPolygon`` geometries in its
+    features.  You need to watch out for this when creating your models
+    as a GeoDjango ``PolygonField`` will not accept a ``MultiPolygon`` 
+    type geometry -- thus a ``MultiPolygonField`` is used in our model's
+    definition instead.
+
+The ``Layer`` may also have a spatial reference system associated with
+it -- if it does, the ``srs`` attribute will return a ``SpatialReference``
+object::
+
+    >>> srs = lyr.srs
+    >>> print srs
+    GEOGCS["GCS_WGS_1984",
+        DATUM["WGS_1984",
+            SPHEROID["WGS_1984",6378137.0,298.257223563]],
+        PRIMEM["Greenwich",0.0],
+        UNIT["Degree",0.0174532925199433]]
+    >>> srs.proj4 # PROJ.4 representation
+    '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs '
+
+Here we've noticed that the shapefile is in the popular WGS84 spatial reference
+system -- in other words, the data uses units of degrees longitude and latitude.
+
+In addition, shapefiles also support attribute fields that may contain 
+additional data.  Here are the fields on the World Borders layer:
+
+    >>> print lyr.fields
+    ['FIPS', 'ISO2', 'ISO3', 'UN', 'NAME', 'AREA', 'POP2005', 'REGION', 'SUBREGION', 'LON', 'LAT']
+
+Here we are examining the OGR types (e.g., whether a field is an integer or
+a string) associated with each of the fields:
+
+    >>> [fld.__name__ for fld in lyr.field_types]
+    ['OFTString', 'OFTString', 'OFTString', 'OFTInteger', 'OFTString', 'OFTInteger', 'OFTInteger', 'OFTInteger', 'OFTInteger', 'OFTReal', 'OFTReal']
+
+You can iterate over each feature in the layer and extract information from both 
+the feature's geometry (accessed via the ``geom`` attribute) as well as the 
+feature's attribute fields (whose **values** are accessed via ``get()``
+method)::
+
+    >>> for feat in lyr:
+    ...    print feat.get('NAME'), feat.geom.num_points
+    ...
+    Guernsey 18
+    Jersey 26
+    South Georgia South Sandwich Islands 338
+    Taiwan 363
+
+``Layer`` objects may be sliced::
+
+    >>> lyr[0:2]
+    [<django.contrib.gis.gdal.feature.Feature object at 0x2f47690>, <django.contrib.gis.gdal.feature.Feature object at 0x2f47650>]
+
+And individual features may be retrieved by their feature ID::
+
+    >>> feat = lyr[234]
+    >>> print feat.get('NAME')
+    San Marino
+
+Here the boundary geometry for San Marino is extracted and looking 
+exported to WKT and GeoJSON::
+
+    >>> geom = feat.geom
+    >>> print geom.wkt
+    POLYGON ((12.415798 43.957954,12.450554 ...
+    >>> print geom.json
+    { "type": "Polygon", "coordinates": [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...
+
+
+``LayerMapping``
+----------------
+
+We're going to dive right in -- create a file called ``load.py`` inside the
+``world`` application, and insert the following::
+
+    import os
+    from django.contrib.gis.utils import LayerMapping
+    from models import WorldBorders
+
+    world_mapping = {
+        'fips' : 'FIPS',
+        'iso2' : 'ISO2',
+        'iso3' : 'ISO3',
+        'un' : 'UN',
+        'name' : 'NAME',
+        'area' : 'AREA',
+        'pop2005' : 'POP2005',
+        'region' : 'REGION',
+        'subregion' : 'SUBREGION',
+        'lon' : 'LON',
+        'lat' : 'LAT',
+        'mpoly' : 'MULTIPOLYGON',
+    }
+
+    world_shp = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data/TM_WORLD_BORDERS-0.3.shp'))
+
+    def run(verbose=True):
+        lm = LayerMapping(WorldBorders, world_shp, world_mapping, 
+                          transform=False, encoding='iso-8859-1')
+
+        lm.save(strict=True, verbose=verbose)
+
+A few notes about what's going on:
+
+* Each key in the ``world_mapping`` dictionary corresponds to a field in the
+  ``WorldBorders`` model, and the value is the name of the shapefile field 
+  that data will be loaded from. 
+* The key ``mpoly`` for the geometry field is ``MULTIPOLYGON``, the
+  geometry type we wish to import as.  Even if simple polygons are encountered
+  in the shapefile they will automatically be converted into collections prior
+  to insertion into the database.
+* The path to the shapefile is not absolute -- in other words, if you move the
+  ``world`` application (with ``data`` subdirectory) to a different location,
+  then the script will still work.
+* The ``transform`` keyword is set to ``False`` because the data in the
+  shapefile does not need to be converted -- it's already in WGS84 (SRID=4326).
+* The ``encoding`` keyword is set to the character encoding of string values in
+  the shapefile. This ensures that string values are read and saved correctly
+  from their original encoding system.
+
+Afterwards, invoke the Django shell from the ``geodjango`` project directory::
+
+   $ python manage.py shell
+
+Next, import the ``load`` module, call the ``run`` routine, and watch ``LayerMapping``
+do the work::
+
+   >>> from world import load
+   >>> load.run()
+
+
+Try ``ogrinspect``
+------------------
+Now that you've seen how to define geographic models and import data with the 
+``LayerMapping`` utility, it's possible to further automate this process with
+use of the ``ogrinspect`` management command.  The ``ogrinspect`` command 
+introspects a GDAL-supported vector data source (e.g., a shapefile) and 
+generates a model definition and ``LayerMapping`` dictionary automatically.
+
+The general usage of the command goes as follows::
+
+    $ python manage.py ogrinspect <data_source> <model_name> [options]
+
+Where ``data_source`` is the path to the GDAL-supported data source and
+``model_name`` is the name to use for the model.  Command-line options may
+be used to further define how the model is generated.
+
+For example, the following command nearly reproduces the ``WorldBorders`` model
+and mapping dictionary created above, automatically::
+
+    $ python manage.py ogrinspect world/data/TM_WORLD_BORDERS-0.3.shp WorldBorders --srid=4326 --mapping --multi
+
+A few notes about the command-line options given above:
+
+* The ``--srid=4326`` option sets the SRID for the geographic field.
+* The ``--mapping`` option tells ``ogrinspect`` to also generate a 
+  mapping dictionary for use with ``LayerMapping``.
+* The ``--multi`` option is specified so that the geographic field is a
+  ``MultiPolygonField`` instead of just a ``PolygonField``.
+
+The command produces the following output, which may be copied 
+directly into the ``models.py`` of a GeoDjango application::
+
+    # This is an auto-generated Django model module created by ogrinspect.
+    from django.contrib.gis.db import models
+
+    class WorldBorders(models.Model):
+        fips = models.CharField(max_length=2)
+        iso2 = models.CharField(max_length=2)
+        iso3 = models.CharField(max_length=3)
+        un = models.IntegerField()
+        name = models.CharField(max_length=50)
+        area = models.IntegerField()
+        pop2005 = models.IntegerField()
+        region = models.IntegerField()
+        subregion = models.IntegerField()
+        lon = models.FloatField()
+        lat = models.FloatField()
+        geom = models.MultiPolygonField(srid=4326)
+        objects = models.GeoManager()
+
+    # Auto-generated `LayerMapping` dictionary for WorldBorders model
+    worldborders_mapping = {
+        'fips' : 'FIPS',
+        'iso2' : 'ISO2',
+        'iso3' : 'ISO3',
+        'un' : 'UN',
+        'name' : 'NAME',
+        'area' : 'AREA',
+        'pop2005' : 'POP2005',
+        'region' : 'REGION',
+        'subregion' : 'SUBREGION',
+        'lon' : 'LON',
+        'lat' : 'LAT',
+        'geom' : 'MULTIPOLYGON',
+    }
+
+Spatial Queries
+===============
+
+Spatial Lookups
+---------------
+GeoDjango extends the Django ORM and allows the use of spatial lookups.
+Let's do an example where we find the ``WorldBorder`` model that contains
+a point.  First, fire up the management shell::
+
+    $ python manage.py shell
+
+Now, define a point of interest [#]_::
+
+    >>> pnt_wkt = 'POINT(-95.3385 29.7245)'
+
+The ``pnt_wkt`` string represents the point at -95.3385 degrees longitude,
+and 29.7245 degrees latitude.  The geometry is in a format known as 
+Well Known Text (WKT), an open standard issued by the Open Geospatial
+Consortium (OGC). [#]_  Import the ``WorldBorders`` model, and perform
+a ``contains`` lookup using the ``pnt_wkt`` as the parameter::
+
+    >>> from world.models import WorldBorders
+    >>> qs = WorldBorders.objects.filter(mpoly__contains=pnt_wkt)
+    >>> qs
+    [<WorldBorders: United States>]
+
+Here we retrieved a ``GeoQuerySet`` that has only one model: the one
+for the United States (which is what we would expect).  Similarly,
+a `GEOS geometry object`_ may also be used -- here the ``intersects``
+spatial lookup is combined with the ``get`` method to retrieve
+only the ``WorldBorders`` instance for San Marino instead of a queryset::
+
+    >>> from django.contrib.gis.geos import Point
+    >>> pnt = Point(12.4604, 43.9420)
+    >>> sm = WorldBorders.objects.get(mpoly__intersects=pnt)
+    >>> sm
+    <WorldBorders: San Marino>
+
+The ``contains`` and ``intersects`` lookups are just a subset of what's
+available -- the `GeoDjango Database API`_ documentation has more.
+
+.. _GEOS geometry object: geos.html
+.. _GeoDjango Database API: db-api.html
+
+Automatic Spatial Transformations
+---------------------------------
+When querying the spatial database GeoDjango automatically transforms 
+geometries if they're in a different coordinate system.  In the following
+example, the coordinate will be expressed in terms of `EPSG SRID 32140`__,
+a coordinate system specific to south Texas **only** and in units of
+**meters** and not degrees::
+
+    >>> from django.contrib.gis.geos import *
+    >>> pnt = Point(954158.1, 4215137.1, srid=32140)
+
+Note that ``pnt`` may also constructed with EWKT, an "extended" form of
+WKT that includes the SRID::
+
+    >>> pnt = GEOSGeometry('SRID=32140;POINT(954158.1 4215137.1)')
+
+When using GeoDjango's ORM, it will automatically wrap geometry values
+in transformation SQL, allowing the developer to work at a higher level
+of abstraction::
+
+    >>> qs = WorldBorders.objects.filter(mpoly__intersects=pnt)
+    >>> qs.query.as_sql() # Generating the SQL
+    ('SELECT "world_worldborders"."id", "world_worldborders"."name", "world_worldborders"."area",
+    "world_worldborders"."pop2005", "world_worldborders"."fips", "world_worldborders"."iso2",
+    "world_worldborders"."iso3", "world_worldborders"."un", "world_worldborders"."region",
+    "world_worldborders"."subregion", "world_worldborders"."lon", "world_worldborders"."lat", 
+    "world_worldborders"."mpoly" FROM "world_worldborders" 
+    WHERE ST_Intersects("world_worldborders"."mpoly", ST_Transform(%s, 4326))',
+    (<django.contrib.gis.db.backend.postgis.adaptor.PostGISAdaptor object at 0x25641b0>,))
+    >>> qs # printing evaluates the queryset
+    [<WorldBorders: United States>]   
+
+__ http://spatialreference.org/ref/epsg/32140/
+
+Lazy Geometries
+---------------
+Geometries come to GeoDjango in a standardized textual representation.  Upon
+access of the geometry field, GeoDjango creates a `GEOS geometry object`_, 
+exposing powerful functionality, such as serialization properties for 
+popular geospatial formats::
+
+    >>> sm = WorldBorders.objects.get(name='San Marino')
+    >>> sm.mpoly
+    <MultiPolygon object at 0x24c6798>
+    >>> sm.mpoly.wkt # WKT 
+    MULTIPOLYGON (((12.4157980000000006 43.9579540000000009, 12.4505540000000003 43.9797209999999978, ...
+    >>> sm.mpoly.wkb # WKB (as Python binary buffer)
+    <read-only buffer for 0x1fe2c70, size -1, offset 0 at 0x2564c40>
+    >>> sm.mpoly.geojson # GeoJSON (requires GDAL)
+    '{ "type": "MultiPolygon", "coordinates": [ [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...
+
+This includes access to all of the advanced geometric operations provided by
+the GEOS library::
+
+    >>> pnt = Point(12.4604, 43.9420)
+    >>> sm.mpoly.contains(pnt)
+    True
+    >>> pnt.contains(sm.mpoly)
+    False
+
+``GeoQuerySet`` Methods
+-----------------------
+
+
+Putting your data on the map
+============================
+
+Google
+------
+
+Geographic Admin
+----------------
+
+Basics
+^^^^^^
+
+GeoDjango also supplements the Django admin by allowing users to create 
+and modify geometries on a JavaScript slippy map (powered by `OpenLayers`_).
+
+Let's dive in again -- create a file called ``admin.py`` inside the 
+``world`` application, and insert the following::
+
+    from django.contrib.gis import admin
+    from models import WorldBorders
+
+    admin.site.register(WorldBorders, admin.GeoModelAdmin)
+
+Next, edit your ``urls.py`` in the ``geodjango`` project folder to look
+as follows::
+
+    from django.conf.urls.defaults import *
+    from django.contrib.gis import admin
+
+    admin.autodiscover()
+
+    urlpatterns = patterns('',
+                           (r'^admin/(.*)', admin.site.root),
+                           )
+
+Start up the Django development server::
+
+    $ python manage.py runserver
+
+Finally, browse to ``http://localhost:8000/admin/``, and log in with the admin
+user created after running ``syncdb``.  Browse to any of the ``WorldBorders``
+entries -- the borders may be edited by clicking on a polygon and dragging
+the vertexes to the desired position.
+
+.. _OpenLayers: http://openlayers.org/
+.. _spherical mercator projection be added: install.html#addgoogleprojection
+.. _PROJ.4 installation instructions: install.html#proj4
+.. _Open Street Map: http://openstreetmap.org/
+.. _Vector Map Level 0: http://earth-info.nga.mil/publications/vmap0.html
+.. _Metacarta: http://metacarta.com
+
+``OSMGeoAdmin``
+^^^^^^^^^^^^^^^
+
+With the ``OSMGeoAdmin``, GeoDjango uses a `Open Street Map`_ layer in the admin.
+This provides more context (including street and thoroughfare details) than
+available with the ``GeoModelAdmin`` (which uses the `Vector Map Level 0`_
+WMS data set hosted at `Metacarta`_).
+
+First, there are some important requirements and limitations:
+
+* The ``OSMGeoAdmin`` requires that the `spherical mercator projection be added`_
+  to the to be added to the PostGIS ``spatial_ref_sys`` table.
+* ``OSMGeoAdmin`` does not work with MySQL and Oracle spatial backends at
+  this time.
+* The PROJ.4 datum shifting files must be installed (see the
+  `PROJ.4 installation instructions`_ for more details).
+
+If you meet these requirements, then just substitute in the ``OSMGeoAdmin``
+option class in your ``admin.py`` file::
+
+    admin.site.register(WorldBorders, admin.OSMGeoAdmin)
+
+.. rubric:: Footnotes
+
+.. [#] Special thanks to Bjørn Sandvik of `thematicmapping.org <http://thematicmapping.org>`_ for providing and maintaining this data set.
+.. [#] GeoDjango basic apps was written by Dane Springmeyer, Josh Livni, and Christopher Schmidt.
+.. [#] Here the point is for the `University of Houston Law Center <http://www.law.uh.edu/>`_ .
+.. [#] Open Geospatial Consortium, Inc., `OpenGIS Simple Feature Specification For SQL <http://www.opengis.org/docs/99-049.pdf>`_, Document 99-049.
Index: docs/ref/contrib/gis/geoip.txt
===================================================================
--- docs/ref/contrib/gis/geoip.txt	(revision 0)
+++ docs/ref/contrib/gis/geoip.txt	(revision 0)
@@ -0,0 +1,179 @@
+==============================
+GeoIP API
+==============================
+
+The ``GeoIP`` object is a ctypes wrapper for the
+`MaxMind GeoIP C API`__. [#]_  This interface is a BSD-licensed alternative
+to the GPL-licensed `Python GeoIP`__ interface provided by MaxMind.
+
+In order to perform IP-based geolocation, the ``GeoIP`` object requires 
+the GeoIP C libary and either the GeoIP `Country`__ or `City`__ 
+datasets in binary format (the CSV files will not work!).  These datasets may be 
+`downloaded from MaxMind`__.  Grab the ``GeoIP.dat.gz`` and ``GeoLiteCity.dat.gz``
+and unzip them in a directory corresponding to what you set 
+``GEOIP_PATH`` with in your settings.  See the example and reference below
+for more details.
+
+__ http://www.maxmind.com/app/c
+__ http://www.maxmind.com/app/python
+__ http://www.maxmind.com/app/country
+__ http://www.maxmind.com/app/city
+__ http://www.maxmind.com/download/geoip/database/
+
+Example
+===========================
+
+Assuming you have the GeoIP C library installed, here is an example of its
+usage::
+
+     >>> from django.contrib.gis.utils import GeoIP
+     >>> g = GeoIP()
+     >>> g.country('google.com')
+     {'country_code': 'US', 'country_name': 'United States'}
+     >>> g.city('72.14.207.99')
+     {'area_code': 650,
+     'city': 'Mountain View',
+     'country_code': 'US',
+     'country_code3': 'USA',
+     'country_name': 'United States',
+     'dma_code': 807,
+     'latitude': 37.419200897216797,
+     'longitude': -122.05740356445312,
+     'postal_code': '94043',
+     'region': 'CA'}
+     >>> g.lat_lon('salon.com')
+     (37.789798736572266, -122.39420318603516)
+     >>> g.lon_lat('uh.edu')
+     (-95.415199279785156, 29.77549934387207) 
+     >>> g.geos('24.124.1.80').wkt
+     'POINT (-95.2087020874023438 39.0392990112304688)'
+
+Initialization
+==============================
+
+The ``GeoIP`` object does not require any parameters to use the default 
+settings.  However, at the very least the ``GEOIP_PATH`` setting should
+be set with the path of the location of your GeoIP data sets.  The 
+following intialization keywords may be used to customize any of the 
+defaults. 
+
+    ===================  ======================================================
+    Keyword Arguments    Description
+    ===================  ======================================================
+    ``path``             Base directory to where GeoIP data is located or the 
+                         full path to where the city or country data files 
+                         (.dat) are located.  Assumes that both the city and 
+                         country data sets are located in this directory; 
+                         overrides the ``GEOIP_PATH`` settings attribute.
+
+    ``cache``            The cache settings when opening up the GeoIP datasets,
+                         and may be an integer in (0, 1, 2, 4) corresponding to
+                         the ``GEOIP_STANDARD``, ``GEOIP_MEMORY_CACHE``, 
+                         ``GEOIP_CHECK_CACHE``, and ``GEOIP_INDEX_CACHE`` 
+                         ``GeoIPOptions`` C API settings, respectively. 
+                         Defaults to 0 (``GEOIP_STANDARD``) -- see the cache
+                         settings table below for more details.
+ 
+    ``country``          The name of the GeoIP country data file.  Defaults
+                         to ``GeoIP.dat``.  Setting this keyword overrides the 
+                         ``GEOIP_COUNTRY`` settings attribute.
+
+    ``city``             The name of the GeoIP city data file.  Defaults to
+                         ``GeoLiteCity.dat``.  Setting this keyword overrides
+                         the ``GEOIP_CITY`` settings attribute.
+    ===================  ======================================================
+
+``GeoIP`` Methods
+==========================
+
+Querying
+--------------------------
+
+All the following querying routines may take either a string IP address
+or a fully qualified domain name (FQDN).  For example, both 
+``'24.124.1.80'`` and ``'djangoproject.com'`` would be valid query 
+parameters. 
+
+``city(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+Returns a dictionary of city information for the given query.  Some
+of the values in the dictionary may be undefined (``None``).
+
+``country(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+Returns a dictionary with the country code and country for the given 
+query.
+
+``country_code(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``country_name(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Coordinate Retrieval
+--------------------------
+
+``coords(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``lon_lat(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``lat_lon(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``geos(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+GeoIP Database Information
+---------------------------
+
+``country_info``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+This property returns information about the GeoIP country database.
+
+``city_info``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+This property returns information about the GeoIP city database.
+
+``info``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+This property returns information about all GeoIP databases (both city
+and country).
+
+GeoIP-Python API compatibility methods
+----------------------------------------
+
+[explanation]
+
+``open(path, cache)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+This classmethod instantiates the GeoIP object from the given database path
+and given cache setting.
+
+``regioin_by_addr(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``region_by_name(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``record_by_addr(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``record_by_name(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``country_code_by_addr(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``country_code_by_name(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``country_name_by_addr(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``country_name_by_name(query)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. rubric:: Footnotes
+.. [#] GeoIP(R) is a registered trademark of MaxMind, LLC of Boston, Massachusetts.
Index: docs/ref/contrib/gis/install.txt
===================================================================
--- docs/ref/contrib/gis/install.txt	(revision 0)
+++ docs/ref/contrib/gis/install.txt	(revision 0)
@@ -0,0 +1,1174 @@
+======================
+GeoDjango Installation
+======================
+
+Overview
+========
+In general, GeoDjango installation requires:
+
+1. :ref:`python24` and :ref:`django`
+2. :ref:`spatial_database`
+3. :ref:`geospatial_libs`
+
+Details for each of the requirements and installation instructions
+are provided in the sections below.   In addition, platform-specific 
+instructions are available for:
+
+* :ref:`macosx`
+* :ref:`ubuntudebian`
+* :ref:`windows`
+
+.. admonition:: Use the Source
+
+    Because GeoDjango takes advantage of the latest in the open source geospatial
+    software technology, recent versions of the libraries are necessary.  
+    Unfortunately, binary packages are not available on many GNU/Linux systems
+    (GEOS 3, in particular).  Thus, `installation from source`_ may be required.
+    When compiling the libraries from source, please follow the directions closely, 
+    especially if you're a beginner. 
+
+.. _installation from source: install.html#building-from-source
+
+Requirements
+============
+
+.. _python24:
+
+Python 2.4+
+-----------
+Because of heavy use of the decorator syntax, Python 2.4 is minimum
+version supported by GeoDjango. Python 2.5+ is recommended because the 
+`ctypes`__ module comes included; otherwise, 2.4 users will need to 
+`download and install ctypes`__.
+
+__ http://docs.python.org/lib/module-ctypes.html
+__ http://sourceforge.net/project/showfiles.php?group_id=71702
+
+.. _django:
+
+Django
+------
+
+Because GeoDjango is included with Django, please refer to Django's
+`installation instructions`__ for details on how to install.
+
+__ http://docs.djangoproject.com/en/dev/intro/install/
+
+.. _spatial_database:
+
+Spatial Database
+----------------
+PostgreSQL (with PostGIS), MySQL, Oracle, and SQLite (with SpatiaLite) are 
+the spatial databases currently supported.
+
+.. note::
+
+    PostGIS is recommended, because it is the most mature and feature-rich 
+    open source spatial database.
+
+The geospatial libraries required for a GeoDjango installation depends
+on the spatial database used.  The following lists the library requirements,
+supported versions, and any notes for each of the supported database backends:
+
+==================  ==============================  ==================  ==========================================================
+Database            Library Requirements            Supported Versions  Notes
+==================  ==============================  ==================  ==========================================================
+PostgreSQL          GEOS, PROJ.4, PostGIS           8.1+                Requires PostGIS.
+MySQL               GEOS                            5.x                 Not OGC-compliant; limited functionality.
+Oracle              GEOS                            10.2, 11            XE not supported; not tested with 9.
+SQLite              GEOS, GDAL, PROJ.4, SpatiaLite  3.6.2+              Requires SpatiaLite 2.3+, pysqlite2 2.5+, and Django 1.1.
+==================  ==============================  ==================  ==========================================================
+
+.. _geospatial_libs:
+
+Geospatial Libraries
+--------------------
+GeoDjango uses and/or provides interfaces for the the following open source 
+geospatial libraries:
+
+==============  ====================================  ================================  ==========================
+Program         Description                           Required                          Supported Versions
+==============  ====================================  ================================  ==========================
+`GEOS`_         Geometry Engine Open Source           Yes                               3.1.x, 3.0.x
+`PROJ.4`_       Cartographic Projections library      Yes (PostgreSQL and SQLite only)  4.7.x, 4.6.x, 4.5.x, 4.4.x
+`GDAL`_         Geospatial Data Abstraction Library   No (but, required for SQLite)     1.6.x, 1.5.x, 1.4.x
+`GeoIP`_        IP-based geolocation library          No                                1.4.x
+`PostGIS`__     Spatial extensions for PostgreSQL     Yes (PostgreSQL only)             1.4.x, 1.3.x, 1.2.1
+`SpatiaLite`__  Spatial extensions for SQLite         Yes (SQLite only)                 2.3.x
+==============  ====================================  ================================  ==========================
+
+.. admonition::  Install GDAL
+
+    While :ref:`gdalbuild` is not required, it is *recommended*.
+    Some features of GeoDjango (including ``LayerMapping`` and the geographic
+    admin) depend on its functionality.
+
+.. note::
+
+    The GeoDjango interfaces to GEOS, GDAL, and GeoIP may be used
+    independently of Django.  In other words, no database or settings file
+    required -- just import them as normal from ``django.contrib.gis``.
+
+.. _GEOS: geos.html
+.. _GDAL: gdal.html
+.. _GeoIP: geoip.html
+.. _PROJ.4: http://trac.osgeo.org/proj/
+
+__ http://postgis.refractions.net/
+__ http://www.gaia-gis.it/spatialite/index.html
+
+.. _build_from_source:
+
+Building from Source
+====================
+
+When installing from source on UNIX and GNU/Linux systems, please follow
+the installation instructions carefully, and install the libraries in the 
+given order.  If using MySQL or Oracle as the spatial database, only GEOS
+is required.
+
+.. note::
+
+    OS X users are required to install `Apple Developer Tools`_ in order
+    to compile software from source.  This is typically included on your
+    OS X installation DVDs.
+
+.. _Apple Developer Tools: http://developer.apple.com/tools/xcode/
+
+.. _geosbuild:
+
+GEOS
+----
+
+GEOS is a C++ library for performing geometric operations, and is the default
+internal geometry representation used by GeoDjango (it's behind the "lazy"
+geometries).  Specifically, the C API library is called (e.g., ``libgeos_c.so``)
+directly from Python using ctypes.
+
+First, download GEOS 3.1.1 from the refractions website and untar the source 
+archive::
+
+    $ wget http://download.osgeo.org/geos/geos-3.1.1.tar.bz2
+    $ tar xjf geos-3.1.1.tar.bz2
+
+Next, change into the directory where GEOS was unpacked, run the configure 
+script, compile, and install::
+
+    $ cd geos-3.1.1
+    $ ./configure
+    $ make
+    $ sudo make install
+    $ cd ..
+
+Troubleshooting
+^^^^^^^^^^^^^^^
+
+Can't find GEOS Library
+~~~~~~~~~~~~~~~~~~~~~~~
+
+When GeoDjango can't find GEOS, this error is raised::
+
+    ImportError: Could not find the GEOS library (tried "geos_c"). Try setting GEOS_LIBRARY_PATH in your settings.
+
+The most common solution is to properly configure your :ref:`libsettings` *or* set 
+:ref:`geoslibrarypath` in your settings.
+
+If using a binary package of GEOS (e.g., on Ubuntu 8.10), you may need to :ref:`binutils`.
+
+.. _geoslibrarypath:
+
+``GEOS_LIBRARY_PATH``
+~~~~~~~~~~~~~~~~~~~~~
+
+If your GEOS library is in a non-standard location, or you don't want to
+modify the system's library path then the ``GEOS_LIBRARY_PATH`` setting
+may be added to your Django settings file with the full path to the GEOS
+C library.  For example::
+
+    GEOS_LIBRARY_PATH = '/home/bob/local/lib/libgeos_c.so'
+
+.. note::
+
+    The setting must be the *full* path to the **C** shared library; in 
+    other words you want to use ``libgeos_c.so``, not ``libgeos.so``.
+
+.. _proj4:
+
+PROJ.4
+------
+
+`PROJ.4`_ is a library for converting geospatial data to different coordinate 
+reference systems.
+
+First, download the PROJ.4 source code and datum shifting files [#]_::
+
+    $ wget http://download.osgeo.org/proj/proj-4.7.0.tar.gz
+    $ wget http://download.osgeo.org/proj/proj-datumgrid-1.5.zip
+
+Next, untar the source code archive, and extract the datum shifting files in the
+``nad`` subdirectory.  This must be done *prior* to configuration::
+
+    $ tar xzf proj-4.7.0.tar.gz
+    $ cd proj-4.7.0/nad
+    $ unzip ../../proj-datumgrid-1.5.zip
+    $ cd ..
+
+Finally, configure, make and install PROJ.4::
+
+    $ ./configure
+    $ make
+    $ sudo make install
+    $ cd ..
+
+.. _postgis:
+
+PostGIS
+-------
+
+`PostGIS`__ adds geographic object support to PostgreSQL, turning it
+into a spatial database. :ref:`geosbuild` and :ref:`proj4` should be 
+installed prior to building PostGIS.
+
+.. note::
+
+    The `psycopg2`_ module is required for use as the database adaptor 
+    when using GeoDjango with PostGIS.  Thus, the ``DATABASE_ENGINE`` 
+    Django setting needs to be ``postgresql_psycopg2``.
+
+.. _psycopg2: http://initd.org/projects/psycopg2
+
+First download the source archive, and extract::
+
+    $ wget http://postgis.refractions.net/download/postgis-1.4.0.tar.gz
+    $ tar xzf postgis-1.4.0.tar.gz
+    $ cd postgis-1.4.0
+
+Next, configure, make and install PostGIS::
+
+    $ ./configure
+
+.. note::
+    PostGIS versions before 1.4 did not consistently install PostGIS files
+    relative to PostgreSQL, so passing the an extra flag is recommended.
+    Thus, when building PostGIS versions 1.3.x and below modify the configuration
+    command to ensure standard placement of PostGIS SQL files::
+
+         $ ./configure --datadir=`pg_config --sharedir` 
+
+Finally, make and install::
+
+    $ make
+    $ sudo make install
+    $ cd ..
+
+.. note::
+
+    GeoDjango does not automatically create a spatial database.  Please 
+    consult the section on :ref:`spatialdb_template` for more information.
+
+__ http://postgis.refractions.net/
+
+.. _gdalbuild:
+
+GDAL
+----
+
+`GDAL`__ is an excellent open source geospatial library that has support for
+reading most vector and raster spatial data formats.  Currently, GeoDjango only 
+supports GDAL's vector data capabilities [#]_.  :ref:`geosbuild` and :ref:`proj4` 
+should be installed prior to building GDAL.
+
+First download the latest GDAL version and untar the archive::
+
+    $ wget http://download.osgeo.org/gdal/gdal-1.6.2.tar.gz
+    $ tar xzf gdal-1.6.2.tar.gz
+    $ cd gdal-1.6.2
+
+Configure, make and install::
+
+    $ ./configure
+    $ make # Go get some coffee, this takes a while.
+    $ sudo make install
+    $ cd ..
+
+.. note::
+
+   Because GeoDjango has it's own Python interface, the preceding instructions
+   do not build GDAL's own Python bindings.  The bindings may be built by 
+   adding the ``--with-python`` flag when running ``configure``.  See
+   `GDAL/OGR In Python`__ for more information on GDAL's bindings. 
+
+If you have any problems, please see the troubleshooting section below for 
+suggestions and solutions.
+
+__ http://trac.osgeo.org/gdal/
+__ http://trac.osgeo.org/gdal/wiki/GdalOgrInPython
+
+.. _gdaltrouble:
+
+Troubleshooting
+^^^^^^^^^^^^^^^
+
+Can't find GDAL Library
+~~~~~~~~~~~~~~~~~~~~~~~
+
+When GeoDjango can't find the GDAL library, the ``HAS_GDAL`` flag
+will be false::
+
+    >>> from django.contrib.gis import gdal
+    >>> gdal.HAS_GDAL
+    False
+
+The solution is to properly configure your :ref:`libsettings` *or* set 
+:ref:`gdallibrarypath` in your settings.
+
+.. _gdallibrarypath:
+
+``GDAL_LIBRARY_PATH``
+~~~~~~~~~~~~~~~~~~~~~
+
+If your GDAL library is in a non-standard location, or you don't want to
+modify the system's library path then the ``GDAL_LIBRARY_PATH`` setting
+may be added to your Django settings file with the full path to the GDAL
+library.  For example::
+
+    GDAL_LIBRARY_PATH = '/home/sue/local/lib/libgdal.so'
+
+.. _gdaldata:
+
+Can't find GDAL data files (``GDAL_DATA``)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When installed from source, GDAL versions 1.5.1 and below have an autoconf bug 
+that places data in the wrong location. [#]_   This can lead to error messages 
+like this::
+
+    ERROR 4: Unable to open EPSG support file gcs.csv.
+    ...
+    OGRException: OGR failure.
+
+The solution is to set the ``GDAL_DATA`` environment variable to the location of the 
+GDAL data files before invoking Python  (typically ``/usr/local/share``; use 
+``gdal-config --datadir`` to find out). For example::
+
+    $ export GDAL_DATA=`gdal-config --datadir`
+    $ python manage.py shell
+
+If using Apache, you may need to add this environment variable to your configuration 
+file::
+
+    SetEnv GDAL_DATA /usr/local/share
+
+.. _spatialite:
+
+SpatiaLite
+----------
+.. versionadded:: 1.1
+
+.. note::
+
+   Mac OS X users should follow the instructions in the :ref:`kyngchaos` section,
+   as it is much easier than building from source.
+
+`SpatiaLite`__ adds spatial support to SQLite, turning it into a full-featured 
+spatial database.  Because SpatiaLite has special requirements, it typically
+requires SQLite and pysqlite2 (the Python SQLite DB-API adaptor) to be built from 
+source.  :ref:`geosbuild` and :ref:`proj4` should be installed prior to building
+SpatiaLite.
+
+After installation is complete, don't forget to read the post-installation 
+docs on :ref:`create_spatialite_db`.
+
+__ http://www.gaia-gis.it/spatialite/index.html
+
+.. _sqlite:
+
+SQLite
+^^^^^^
+
+Typically, SQLite packages are not compiled to include the `R*Tree module`__ --
+thus it must be compiled from source.  First download the latest amalgamation 
+source archive from the `SQLite download page`__, and extract::
+
+    $ wget http://www.sqlite.org/sqlite-amalgamation-3.6.17.tar.gz
+    $ tar xzf sqlite-amalgamation-3.6.17.tar.gz
+    $ cd sqlite-3.6.17
+
+Next, run the ``configure`` script -- however the ``CFLAGS`` environment variable
+needs to be customized so that SQLite knows to build the R*Tree module::
+
+    $ CFLAGS="-DSQLITE_ENABLE_RTREE=1" ./configure
+    $ make
+    $ sudo make install
+    $ cd ..
+
+.. note::
+
+    If using Ubuntu, installing a newer SQLite from source can be very difficult
+    because it links to the existing ``libsqlite3.so`` in ``/usr/lib`` which 
+    many other packages depend on.  Unfortunately, the best solution at this time
+    is to overwrite the existing library by adding ``--prefix=/usr`` to the
+    ``configure`` command.
+
+__ http://www.sqlite.org/rtree.html
+__ http://www.sqlite.org/download.html
+
+.. _spatialitebuild :
+
+SpatiaLite Library (``libspatialite``) and Tools (``spatialite``)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+After SQLite has been built with the R*Tree module enabled, get the latest
+SpatiaLite library source and tools bundle from the `download page`__::
+
+    $ wget http://www.gaia-gis.it/spatialite/libspatialite-amalgamation-2.3.1.tar.gz
+    $ wget http://www.gaia-gis.it/spatialite/spatialite-tools-2.3.1.tar.gz
+    $ tar xzf libspatialite-amalgamation-2.3.1.tar.gz
+    $ tar xzf spatialite-tools-2.3.1.tar.gz
+
+Prior to attempting to build, please read the important notes below to see if
+customization of the ``configure`` command is necessary.  If not, then run the 
+``configure`` script, make, and install for the SpatiaLite library::
+
+    $ cd libspatialite-amalgamation-2.3.1
+    $ ./configure # May need to modified, see notes below.
+    $ make
+    $ sudo make install
+    $ cd ..
+
+Finally, do the same for the SpatiaLite tools::
+
+    $ cd spatialite-tools-2.3.1   
+    $ ./configure # May need to modified, see notes below.
+    $ make
+    $ sudo make install
+    $ cd ..
+
+.. note::
+
+    If you've installed GEOS and PROJ.4 from binary packages, you will have to specify
+    their paths when running the ``configure`` scripts for *both* the library and the 
+    tools (the configure scripts look, by default, in ``/usr/local``).  For example, 
+    on Debian/Ubuntu distributions that have GEOS and PROJ.4 packages, the command would be::
+    
+       $ ./configure --with-proj-include=/usr/include --with-proj-lib=/usr/lib --with-geos-include=/usr/include --with-geos-lib=/usr/lib
+
+.. note::
+
+    For Mac OS X users building from source, the SpatiaLite library *and* tools 
+    need to be linked into the existing ``iconv`` library. While this happens 
+    automatically on Linux, the ``configure`` scripts need to know about the 
+    specific location on Mac OS X (via modification of the ``CFLAGS`` and 
+    ``LDFLAGS`` environment variables prior to configuration)::
+
+        $ CFLAGS=-I/usr/include LDFLAGS="-L/usr/lib -liconv" ./configure
+
+__ http://www.gaia-gis.it/spatialite/sources.html
+
+.. _pysqlite2:
+
+pysqlite2
+^^^^^^^^^
+
+Because SpatiaLite must be loaded as an external extension, it requires the
+``enable_load_extension`` method, which is only available in versions 2.5+.
+Thus, download pysqlite2 2.5, and untar::
+  
+    $ wget http://pysqlite.googlecode.com/files/pysqlite-2.5.6.tar.gz
+    $ tar xzf pysqlite-2.5.6.tar.gz
+    $ cd pysqlite-2.5.6
+
+Next, use a text editor (e.g., ``emacs`` or ``vi``) to edit the ``setup.cfg`` file
+to look like the following::
+
+    [build_ext]
+    #define=
+    include_dirs=/usr/local/include
+    library_dirs=/usr/local/lib
+    libraries=sqlite3
+    #define=SQLITE_OMIT_LOAD_EXTENSION
+
+.. note::
+
+    The important thing here is to make sure you comment out the the
+    ``define=SQLITE_OMIT_LOAD_EXTENSION`` flag and that the ``include_dirs``
+    and ``library_dirs`` settings are uncommented and set to the appropriate
+    path if the SQLite header files and libraries are not in ``/usr/include``
+    and ``/usr/lib``, respectively.   
+
+After modifying ``setup.cfg`` appropriately, then run the ``setup.py`` script
+to build and install::
+
+    $ sudo python setup.py install
+
+Post-Installation
+=================
+
+.. _spatialdb_template:
+
+Creating a Spatial Database Template for PostGIS
+------------------------------------------------
+
+Creating a spatial database with PostGIS is different than normal because
+additional SQL must be loaded to enable spatial functionality.  Because of 
+the steps in this process, it's better to create a database template that
+can be reused later.
+
+First, you need to be able to execute the commands as a privileged database
+user.  For example, you can use the following to become the ``postgres`` user::
+
+    $ sudo su - postgres
+
+Once you're a database super user, then you may execute the following commands
+to create a PostGIS spatial database template.  If running Ubuntu :ref:`ibex`
+or Debian :ref:`lenny`, please refer to their specific documentation for slight
+modifications to these commands::
+
+    $ POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib
+    $ createdb -E UTF8 template_postgis # Creating the template spatial database.
+    $ createlang -d template_postgis plpgsql # Adding PLPGSQL language support.
+    $ psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';" # Allows non-superusers the ability to create from this template
+    $ psql -d template_postgis -f $POSTGIS_SQL_PATH/postgis.sql # Loading the PostGIS SQL routines
+    $ psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql
+    $ psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables.
+    $ psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"
+
+These commands may be placed in a shell script for later use; for convenience,
+the `create_template_postgis-1.4.sh`__ script is provided here.  If using
+PostGIS 1.3.x, please use the `create_template_postgis-1.3.sh`__ script
+instead as the PostGIS SQL path and file names differ from 1.4.
+
+Afterwards, you may create a spatial database by simply specifying
+``template_postgis`` as the template to use (via the ``-T`` option)::
+
+    $ createdb -T template_postgis <db name>
+
+.. note::
+
+    While the ``createdb`` command does not require database super-user privileges,
+    it must be executed by a database user that has permissions to create databases.
+    You can create such a user with the following command::
+
+        $ createuser --createdb <user>
+
+__ http://geodjango.org/docs/create_template_postgis-1.4.sh
+__ http://geodjango.org/docs/create_template_postgis-1.3.sh
+
+.. _create_spatialite_db:
+
+Creating a Spatial Database for SpatiaLite
+-------------------------------------------
+
+After the SpatiaLite library and tools have been installed, it is now possible
+to create spatial database for use with GeoDjango.  In order to do this, download
+the spatial database initialization SQL from the `SpatiaLite Resources`__ page::
+
+   $ wget http://www.gaia-gis.it/spatialite/init_spatialite-2.3.sql.gz
+   $ gunzip init_spatialite-2.3.sql.gz
+
+Now, the ``spatialite`` command can be used to initialize a spatial database::
+
+   $ spatialite geodjango.db < init_spatialite-2.3.sql
+
+.. note::
+
+    The parameter ``geodjango.db`` is the *filename* of the SQLite database
+    you want to use.  Use the same in the ``DATABASE_NAME`` setting inside
+    your project's ``settings.py``.
+
+
+__ http://www.gaia-gis.it/spatialite/resources.html
+
+
+Add ``django.contrib.gis`` to ``INSTALLED_APPS``
+------------------------------------------------
+
+Like other Django contrib applications, you will *only* need to add 
+``django.contrib.gis`` to ``INSTALLED_APPS`` in your settings.  This is the
+so that ``gis`` templates can be located -- if not done, then features such as
+the geographic admin or KML sitemaps will not function properly.
+
+.. _addgoogleprojection:
+
+Add Google Projection to ``spatial_ref_sys`` table
+--------------------------------------------------
+
+.. note::
+
+    In Django 1.1 this step is no longer required to use the geographic 
+    admin with the OpenStreetMap base layer.
+
+In order to use the geographic admin with the OpenStreetMap base layer
+(e.g., you want to use ``OSMGeoAdmin``), then the so-called "Google" projection 
+must be added to your spatial database's ``spatial_ref_sys`` table.  Invoke
+the Django shell from your project and execute the following command::
+
+    $ ./manage shell
+    >>> from django.contrib.gis.utils import add_postgis_srs
+    >>> add_postgis_srs(900913)
+
+This adds an entry for the 900913 SRID to the ``spatial_ref_sys`` (or equivalent)
+table, making it possible for the spatial database to transform coordinates in 
+this projection.  You only need to execute this command *once* per spatial database.
+
+Troubleshooting
+===============
+
+If you can't find the solution to your problem here then participate in the
+community!  You can:
+
+* Join the ``#geodjango`` IRC channel on FreeNode (may be accessed on the
+  web via `Mibbit`__).  Please be patient and polite -- while you may not 
+  get an immediate response, someone will attempt to answer your question 
+  as soon as they see it.
+* Ask your question on the `GeoDjango`__ mailing list.
+* File a ticket on the `Django trac`__ if you think there's a bug.  Make
+  sure to provide a complete description of the problem, versions used,
+  and specify the component as "GIS".
+
+__ http://www.mibbit.com/?server=irc.freenode.net&channel=%23geodjango
+__ http://groups.google.com/group/geodjango
+__ http://code.djangoproject.com/simpleticket
+
+.. _libsettings:
+
+Library Environment Settings
+----------------------------
+
+By far, the most common problem when installing GeoDjango is that the
+external shared libraries (e.g., for GEOS and GDAL) cannot be located. [#]_
+Typically, the cause of this problem is that the operating system isn't aware 
+of the directory where the libraries built from source were installed.
+
+In general, the library path may be set on a per-user basis by setting
+an environment variable, or by configuring the library path for the entire
+system.
+
+``LD_LIBRARY_PATH`` environment variable
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A user may set this environment variable to customize the library paths
+they want to use.  The typical library directory for software 
+built from source is ``/usr/local/lib``.  Thus, ``/usr/local/lib`` needs
+to be included in the ``LD_LIBRARY_PATH`` variable.  For example, the user 
+could place the following in their bash profile::
+
+    export LD_LIBRARY_PATH=/usr/local/lib
+
+Setting System Library Path
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+On GNU/Linux systems, there is typically a file in ``/etc/ld.so.conf``, which may include
+additional paths from files in another directory, such as ``/etc/ld.so.conf.d``.
+As the root user, add the custom library path (like ``/usr/local/lib``) on a  
+new line in ``ld.so.conf``.  This is *one* example of how to do so::
+
+    $ sudo echo /usr/local/lib >> /etc/ld.so.conf
+    $ sudo ldconfig
+
+For OpenSolaris users, the system library path may be modified using the
+``crle`` utility.  Run ``crle`` with no options to see the current configuration
+and use ``crle -l`` to set with the new library path.  Be *very* careful when
+modifying the system library path::
+
+    # crle -l $OLD_PATH:/usr/local/lib
+
+.. _binutils:
+
+Install ``binutils``
+^^^^^^^^^^^^^^^^^^^^
+
+GeoDjango uses the ``find_library`` function (from the ``ctypes.util`` Python
+module) to discover libraries.  The ``find_library`` routine uses a program
+called ``objdump`` (part of the ``binutils`` package) to verify a shared 
+library on GNU/Linux systems.  Thus, if ``binutils`` is not installed on your
+Linux system then Python's ctypes may not be able to find your library even if 
+your library path is set correctly and geospatial libraries were built perfectly.
+
+The ``binutils`` package may be installed on Debian and Ubuntu systems using the
+following command::
+
+    $ sudo apt-get install binutils
+
+Similarly, on Red Hat and CentOS systems::
+
+    $ sudo yum install binutils
+
+Platform Specific Instructions
+==============================
+
+.. _macosx:
+
+Mac OS X
+--------
+
+Because of the variety of packaging systems available for OS X, users have
+several different options for installing GeoDjango.  These options are:
+
+* :ref:`kyngchaos`
+* :ref:`fink`
+* :ref:`macports`
+* :ref:`build_from_source`
+
+.. note::
+
+    Currently, the easiest and recommended approach for installing GeoDjango
+    on OS X is to use the KyngChaos packages.  
+
+This section also includes instructions for installing an upgraded version 
+of :ref:`macosx_python` from packages provided by the Python Software 
+Foundation, however, this is not required.
+
+.. _macosx_python:
+
+Python
+^^^^^^
+
+Although OS X comes with Python installed, users can use framework
+installers (`2.5`__ and `2.6`__ are available) provided by 
+the Python Software Foundation.  An advantage to using the installer is 
+that OS X's Python will remain "pristine" for internal operating system
+use.
+
+__ http://python.org/ftp/python/2.5.4/python-2.5.4-macosx.dmg
+__ http://python.org/ftp/python/2.6.2/python-2.6.2-macosx2009-04-16.dmg
+
+.. note::
+  
+    You will need to modify the ``PATH`` environment variable in your
+    ``.profile`` file so that the new version of Python is used when
+    ``python`` is entered at the command-line::
+
+        export PATH=/Library/Frameworks/Python.framework/Versions/Current/bin:$PATH
+
+.. _kyngchaos:
+
+KyngChaos Packages
+^^^^^^^^^^^^^^^^^^
+
+William Kyngesburye provides a number of `geospatial library binary packages`__ 
+that make it simple to get GeoDjango installed on OS X without compiling 
+them from source.  However, the `Apple Developer Tools`_ are still necessary
+for compiling the Python database adapters :ref:`psycopg2_kyngchaos` (for PostGIS)
+and :ref:`pysqlite2_kyngchaos` (for SpatiaLite).  
+
+.. note::
+
+    SpatiaLite users should consult the :ref:`spatialite_kyngchaos` section 
+    after installing the packages for additional instructions.
+
+Download the framework packages for:
+
+* UnixImageIO
+* PROJ
+* GEOS
+* SQLite3 (includes the SpatiaLite library)
+* GDAL
+
+Install the packages in the order they are listed above, as the GDAL and SQLite
+packages require the packages listed before them.  Afterwards, you can also
+install the KyngChaos binary packages for `PostgreSQL and PostGIS`__.
+
+After installing the binary packages, you'll want to add the following to
+your ``.profile`` to be able to run the package programs from the command-line::
+
+    export PATH=/Library/Frameworks/UnixImageIO.framework/Programs:$PATH
+    export PATH=/Library/Frameworks/PROJ.framework/Programs:$PATH
+    export PATH=/Library/Frameworks/GEOS.framework/Programs:$PATH
+    export PATH=/Library/Frameworks/SQLite3.framework/Programs:$PATH
+    export PATH=/Library/Frameworks/GDAL.framework/Programs:$PATH
+    export PATH=/usr/local/pgsql/bin:$PATH
+
+__ http://www.kyngchaos.com/wiki/software:frameworks
+__ http://www.kyngchaos.com/wiki/software:postgres
+
+.. note::
+
+    Use of these binaries requires Django 1.0.3 and above.  If you are
+    using a previous version of Django (like 1.0.2), then you will have
+    to add the the following in your settings::
+
+        GEOS_LIBRARY_PATH='/Library/Frameworks/GEOS.framework/GEOS'
+        GDAL_LIBRARY_PATH='/Library/Frameworks/GDAL.framework/GDAL'
+
+.. _psycopg2_kyngchaos:
+
+psycopg2
+~~~~~~~~
+
+After you've installed the KyngChaos binaries and modified your ``PATH``, as
+described above, ``psycopg2`` may be installed using the following command::
+
+    $ sudo python easy_install psycopg2
+
+.. note::
+
+   To use ``easy_install`` you'll need to install Python's `setuptools`_.
+
+.. _setuptools: http://pypi.python.org/pypi/setuptools
+
+.. _pysqlite2_kyngchaos:
+
+pysqlite2
+~~~~~~~~~
+
+Follow the :ref:`pysqlite2` source install instructions, however, 
+when editing the ``setup.cfg`` use the following instead::
+
+    [build_ext]
+    #define=
+    include_dirs=/Library/Frameworks/SQLite3.framework/unix/include
+    library_dirs=/Library/Frameworks/SQLite3.framework/unix/lib
+    libraries=sqlite3
+    #define=SQLITE_OMIT_LOAD_EXTENSION
+
+.. _spatialite_kyngchaos:
+
+SpatiaLite
+~~~~~~~~~~
+
+When :ref:`create_spatialite_db`, the ``spatialite`` program is required.
+However, instead of attempting to compile the SpatiaLite tools from source,
+download the `SpatiaLite Binaries`__ for OS X, and install ``spatialite`` in a 
+location available in your ``PATH``.  For example::
+
+    $ curl -O http://www.gaia-gis.it/spatialite/spatialite-tools-osx-x86-2.3.1.tar.gz
+    $ tar xzf spatialite-tools-osx-x86-2.3.1.tar.gz
+    $ cd spatialite-tools-osx-x86-2.3.1/bin
+    $ sudo cp spatialite /Library/Frameworks/SQLite3.framework/Programs
+
+Finally, for GeoDjango to be able to find the KyngChaos SpatiaLite library,
+add the following to your ``settings.py``::
+
+    SPATIALITE_LIBRARY_PATH='/Library/Frameworks/SQLite3.framework/SQLite3'
+
+__ http://www.gaia-gis.it/spatialite/binaries.html
+
+.. _fink:
+
+Fink
+^^^^
+
+`Kurt Schwehr`__ has been gracious enough to create GeoDjango packages for users
+of the `Fink`__ package system.  The following packages are available, depending
+on which version of Python you want to use:
+
+* ``django-gis-py26``
+* ``django-gis-py25``
+* ``django-gis-py24``
+
+__ http://schwehr.org/blog/
+__ http://www.finkproject.org/
+
+.. _macports:
+
+MacPorts
+^^^^^^^^
+
+`MacPorts`__ may be used to install GeoDjango prerequisites on Macintosh 
+computers running OS X.  Because MacPorts still builds the software from source,
+the `Apple Developer Tools`_ are required. 
+
+Summary::
+
+    $ sudo port install postgresql83-server
+    $ sudo port install geos
+    $ sudo port install proj
+    $ sudo port install postgis
+    $ sudo port install gdal
+    $ sudo port install libgeoip  
+
+.. note::
+
+    You will also have to modify the ``PATH`` in your ``.profile`` so
+    that the MacPorts programs are accessible from the command-line::
+
+        export PATH=/opt/local/bin:/opt/local/lib/postgresql83/bin
+
+    In addition, add the ``FALLBACK_DYLD_LIBRARY_PATH`` setting so that
+    the libraries can be found by Python::
+
+        export FALLBACK_DYLD_LIBRARY_PATH=/opt/local/lib:/opt/local/lib/postgresql83
+
+__ http://www.macports.org/
+
+.. _ubuntudebian:
+
+Ubuntu & Debian GNU/Linux
+-------------------------
+
+.. _ubuntu:
+
+Ubuntu
+^^^^^^
+
+.. _heron:
+
+8.04 and lower
+~~~~~~~~~~~~~~
+
+The 8.04 (and lower) versions of Ubuntu use GEOS v2.2.3 in their binary packages, 
+which is incompatible with GeoDjango.  Thus, do *not* use the binary packages 
+for GEOS or PostGIS and build some prerequisites from source, per the instructions 
+in this document; however, it is okay to use the PostgreSQL binary packages.
+
+For more details, please see the Debian instructions for :ref:`etch` below.
+
+.. _ibex:
+
+8.10
+~~~~
+
+Use the synaptic package manager to install the following packages::
+
+    $ sudo apt-get install binutils libgdal1-1.5.0 postgresql-8.3-postgis postgresql-server-dev-8.3 python-psycopg2 python-setuptools
+
+Afterwards, you may install Django with Python's ``easy_install`` script (the
+Ubuntu package ``python-django`` uses an older version missing several
+important bug fixes for GeoDjango)::
+
+    $ sudo easy_install Django
+
+That's it!  For the curious, the required binary prerequisites packages are:
+
+* ``binutils``: for ctypes to find libraries
+* ``postgresql-8.3``
+* ``postgresql-server-dev-8.3``: for ``pg_config``
+* ``postgresql-8.3-postgis``: for PostGIS 1.3.3
+* ``libgeos-3.0.0``, and ``libgeos-c1``: for GEOS 3.0.0
+* ``libgdal1-1.5.0``: for GDAL 1.5.0 library
+* ``proj``: for PROJ 4.6.0 -- but no datum shifting files, see note below
+* ``python-psycopg2``
+* ``python-setuptools``: for ``easy_install``
+
+Optional packages to consider:
+
+* ``libgeoip1``: for `GeoIP`_ support
+* ``gdal-bin``: for GDAL command line programs like ``ogr2ogr``
+* ``python-gdal`` for GDAL's own Python bindings -- includes interfaces for raster manipulation
+
+.. note::
+   
+    The Ubuntu ``proj`` package does not come with the datum shifting files
+    installed, which will cause problems with the geographic admin because 
+    the ``null`` datum grid is not available for transforming geometries to the
+    spherical mercator projection. A solution is to download the 
+    datum-shifting files, create the grid file, and install it yourself::
+
+        $ wget http://download.osgeo.org/proj/proj-datumgrid-1.4.tar.gz
+        $ mkdir nad
+        $ cd nad
+        $ tar xzf ../proj-datumgrid-1.4.tar.gz
+        $ nad2bin null < null.lla
+        $ sudo cp null /usr/share/proj
+
+    Otherwise, the Ubuntu ``proj`` package is fine for general use as long as you
+    do not plan on doing any database transformation of geometries to the 
+    Google projection (900913).
+
+.. note::
+
+    The PostGIS SQL files are not placed the PostgreSQL share directory in the
+    Ubuntu packages.  Use the `create_template_postgis-debian.sh`__ script
+    instead when :ref:`spatialdb_template`.
+
+__ http://geodjango.org/docs/create_template_postgis-debian.sh
+
+.. _debian:
+
+Debian
+------
+
+.. _etch:
+
+4.0 (Etch)
+^^^^^^^^^^
+The situation here is the same as that of Ubuntu :ref:`heron` -- in other words,
+some packages must be built from source to work properly with GeoDjango.
+
+Binary Packages
+~~~~~~~~~~~~~~~
+The following command will install acceptable binary packages, as well as
+the development tools necessary to build the rest of the requirements::
+
+    $ sudo apt-get install binutils bzip2 gcc g++ flex make postgresql-8.1 postgresql-server-dev-8.1 python-ctypes python-psycopg2 python-setuptools
+
+Required package information:
+
+* ``binutils``: for ctypes to find libraries
+* ``bzip2``: for decompressing the source packages
+* ``gcc``, ``g++``, ``make``: GNU developer tools used to compile the libraries
+* ``flex``: required to build PostGIS
+* ``postgresql-8.1``
+* ``postgresql-server-dev-8.1``: for ``pg_config``
+* ``python-ctypes``: Python 2.4 needs to have ctypes installed separately
+* ``python-psycopg2``
+* ``python-setuptools``: for ``easy_install``
+
+Optional packages:
+
+* ``libgeoip``: for `GeoIP`_ support
+
+Source Packages
+~~~~~~~~~~~~~~~
+You will still have to install :ref:`geosbuild`, :ref:`proj4`,
+:ref:`postgis`, and :ref:`gdalbuild` from source.  Please follow the 
+directions carefully.
+
+.. _lenny:
+
+5.0 (Lenny)
+^^^^^^^^^^^
+This version is comparable to Ubuntu :ref:`ibex`, so the command 
+is very similar::
+
+    $ sudo apt-get install binutils libgdal1-1.5.0 postgresql-8.3 postgresql-8.3-postgis postgresql-server-dev-8.3 python-psycopg2 python-setuptools
+
+This assumes that you are using PostgreSQL version 8.3. Else, replace ``8.3``
+in the above command with the appropriate PostgreSQL version.
+
+.. note::
+
+   Please read the note in the Ubuntu :ref:`ibex` install documentation
+   about the ``proj`` package -- it also applies here because the package does
+   not include the datum shifting files.
+
+.. _post_install:
+
+Post-installation Notes
+~~~~~~~~~~~~~~~~~~~~~~~
+
+If the PostgreSQL database cluster was not initiated after installing, then it
+can be created (and started) with the following command::
+
+    $ sudo pg_createcluster --start 8.3 main
+
+Afterwards, the ``/etc/init.d/postgresql-8.3`` script should be used to manage
+the starting and stopping of PostgreSQL.
+
+In addition, the SQL files for PostGIS are placed in a different location on
+Debian 5.0 . Thus when :ref:`spatialdb_template` either:
+
+* Create a symbolic link to these files::
+
+    $ sudo ln -s /usr/share/postgresql-8.3-postgis/{lwpostgis,spatial_ref_sys}.sql /usr/share/postgresql/8.3
+
+  If not running PostgreSQL 8.3, then  replace ``8.3`` in the command above with the correct version.
+
+* Or use the `create_template_postgis-debain.sh`__ to create the spatial database.
+  If you're PostgreSQL version is not 8.3, you will have to modify the 
+  ``POSTGIS_SQL_PATH`` variable in the script.
+
+__ http://geodjango.org/docs/create_template_postgis-debian.sh
+
+.. _windows:
+
+Windows XP
+----------
+
+Python
+^^^^^^
+
+First, download the `Python 2.6 installer`__ from the Python website.  Next,
+execute the installer and use defaults, e.g., keep 'Install for all users' 
+checked and the installation path set as ``C:\Python26``.
+
+.. note::
+
+    You may already have a version of Python installed in ``C:\python`` as ESRI
+    products sometimes install a copy there.  *You should still install a 
+    fresh version of Python 2.6.*
+
+__ http://python.org/ftp/python/2.6.2/python-2.6.2.msi
+
+PostgreSQL
+^^^^^^^^^^
+
+First, select a mirror and download the latest `PostgreSQL 8.3 installer`__ from
+the EnterpriseDB website.
+
+.. note::
+
+   PostgreSQL 8.3 is required because PostGIS is not available yet for 8.4.
+
+After downloading, simply click on the installer, follow the 
+on-screen directions, and keep the default options (e.g., keep the installation 
+path as ``C:\Program Files\PostgreSQL\8.3``).
+
+.. note::
+
+    This PostgreSQL installation process will create both a new windows user to be the 
+    'postgres service account' and a special 'postgres superuser' to own the database 
+    cluster. You will be prompted to set a password for both users (make sure to write 
+    them down!). To see basic details on the 'service user' account right click on 
+    'My Computer' and select 'Manage' or go to: Control Panel -> Administrative Tools -> 
+    Computer Management -> System Tools -> Local Users and Groups.
+
+If installed successfully, the PostgreSQL server will run in the background each time 
+the system as started as a Windows service.  When finished, the installer should launch 
+the Application Stack Builder (ASB) -- use this to install PostGIS, see instructions
+below for more details.  A 'PostgreSQL 8.3' start menu group should be created that
+contains shortcuts for the ASB and 'Command Prompt', which launches a terminal window
+in the PostgreSQL directory.
+
+__ http://www.enterprisedb.com/products/pgdownload.do#windows
+
+PostGIS
+^^^^^^^
+
+From the Application Stack Builder (Programs -> PostgreSQL 8.3), select 
+'PostgreSQL Database Server 8.3 on port 5432' from the drop down menu.  Next, 
+select 'PostGIS 1.3.6 for PostgreSQL 8.3' from the 'Spatial Extensions' tree
+in the list.  Select only the default options during install (do not uncheck 
+the option to create a default PostGIS database).
+
+.. note::
+
+    You will be prompted to enter your 'postgres superuser' password in the 
+    'Database Connection Information' dialog.
+
+psycopg2
+^^^^^^^^
+
+The ``psycopg2`` Python module provides the interface between Python and the
+PostgreSQL database.  Download the `Windows installer`__ (v2.0.10) and run 
+using the default settings. [#]_
+
+__ http://www.stickpeople.com/projects/python/win-psycopg/psycopg2-2.0.10.win32-py2.6-pg8.3.7-release.exe
+
+GeoDjango Installer
+^^^^^^^^^^^^^^^^^^^
+
+Download the `GeoDjango Installer`__; this was created [#]_ to simplify the rest
+of the process for installing GeoDjango on Windows platforms.  The installer
+automatically installs Django 1.1, GDAL 1.6.0, PROJ 4.6.1 (including datum grid
+files), and configures the necessary environment variables.
+
+Once the installer has completed, log out and log back in so that the 
+modifications to the system environment variables take effect, and you
+should be good to go.
+
+.. note::
+
+    The installer modifies the system ``Path`` environment variable to
+    include ``C:\Program Files\PostgreSQL\8.3\bin`` and 
+    ``C:\Program Files\GeoDjango\bin``.  This is required so that Python
+    may find the GEOS DLL provided by PostGIS and the GDAL DLL provided
+    by the installer. The installer also sets the ``GDAL_DATA`` and 
+    ``PROJ_LIB`` environment variables.
+
+__ http://geodjango.org/windows/GeoDjango_Installer.exe
+
+.. rubric:: Footnotes
+.. [#] The datum shifting files are needed for converting data to and from certain projections.
+       For example, the PROJ.4 string for the `Google projection (900913) <http://spatialreference.org/ref/epsg/900913/proj4>`_ 
+       requires the ``null`` grid file only included in the extra datum shifting files.  
+       It is easier to install the shifting files now, then to have debug a problem caused by their absence later.
+.. [#] Specifically, GeoDjango provides support for the `OGR <http://gdal.org/ogr>`_ library, a component of GDAL.
+.. [#] See `GDAL ticket #2382 <http://trac.osgeo.org/gdal/ticket/2382>`_.
+.. [#] GeoDjango uses the `find_library <http://docs.python.org/library/ctypes.html#finding-shared-libraries>`_
+       routine from ``ctypes.util`` to locate shared libraries. 
+.. [#] The ``psycopg2`` Windows installers are packaged and maintained by 
+       `Jason Erickson <http://www.stickpeople.com/projects/python/win-psycopg/>`_. 
+.. [#] The source code for the installer is available in the `nsis_installer <http://geodjango.org/hg/nsis_installer/>`_ 
+       GeoDjango mercurial repository.
Index: docs/ref/contrib/gis/gdal.txt
===================================================================
--- docs/ref/contrib/gis/gdal.txt	(revision 0)
+++ docs/ref/contrib/gis/gdal.txt	(revision 0)
@@ -0,0 +1,801 @@
+========
+GDAL API
+========
+
+`GDAL`__ stands for **G**\ eospatial **D**\ ata **A**\ bstraction **L**\ ibrary,
+and is a veritable "swiss army knife" of GIS data functionality.  It
+also includes the `OGR`__ Simple Features Library, which specializes
+in reading and writing geographic data in a variety of standard
+formats.
+
+__ http://www.gdal.org/
+__ http://www.gdal.org/ogr/
+
+Overview
+========
+
+Sample Data
+-----------
+
+The GDAL/OGR tools described here are designed to help you read in
+your geospatial data, in order for most of them to be useful you have
+to have some data to work with.  If you're starting out and don't yet
+have any data of your own to use, GeoDjango comes with a number of
+simple data sets that you can use for testing.  This snippet will
+determine where these sample files are installed on your computer::
+
+    >>> import os
+    >>> import django.contrib.gis
+    >>> GIS_PATH = os.path.dirname(django.contrib.gis.__file__)
+    >>> CITIES_PATH = os.path.join(GIS_PATH, 'tests/layermap/cities/cities.shp')
+
+``DataSource``
+==============
+
+``DataSource`` is a wrapper for the OGR data source object that
+supports reading data from a variety of OGR-supported geospatial file
+formats and data sources using a simple, consistent interface.  Each
+data source is represented by a ``DataSource`` object which contains
+one or more layers of data.  Each layer, represented by a ``Layer``
+object, contains some number of geographic features, as well as
+information about the type of features contained in that layer (e.g.
+points, polygons, etc.), as well as the names and types of any
+additional fields of data that may be associated with each feature in
+that layer.
+
+The constructor for the ``DataSource`` object normally takes just a
+single parameter, the path of the file you want to read.  However, OGR
+also supports a variety of more complex data sources, including
+databases, that you access by passing it a special name string instead
+of a path.  For more information, see the `OGR Vector Formats`__
+documentation.  The ``name`` property of a ``DataSource`` will tell 
+you the OGR name of the underlying data source that it is using.
+
+Once you've created your ``DataSource``, you can find out how many 
+layers of data it contains by accessing the ``layer_count`` property, 
+or (equivalently) by using the ``len()`` function.  For information on 
+accessing the layers of data themselves, see the next section::
+
+    >>> from django.contrib.gis.gdal import DataSource
+    >>> ds = DataSource(CITIES_PATH)
+    >>> ds.name                         # The exact filename may be different on your computer
+    '/usr/local/lib/python2.6/site-packages/django/contrib/gis/tests/layermap/cities/cities.shp'
+    >>> ds.layer_count                  # This file only contains one layer
+    1
+
+__ http://www.gdal.org/ogr/ogr_formats.html
+
+``Layer``
+---------
+
+``Layer`` is a wrapper for a layer of data in a ``DataSource`` object.
+You never create a ``Layer`` object directly.  Instead, you retrieve
+them from a ``DataSource`` object, which is essentially a standard
+Python container of ``Layer`` objects.  For example, you can access a
+specific layer by its index (e.g. ``ds[0]`` to access the first
+layer), or you can iterate over all the layers in the container in a
+``for`` loop.  The ``Layer`` itself acts as a container for geometric 
+features.
+
+All the features in a given layer have the same geometry type.  The
+``geom_type`` property of a layer is an ``OGRGeomType`` object,
+discussed below, that identifies the feature type.  We can use it 
+to print out some basic information about each layer in a data source::
+
+    >>> for layer in ds:
+    ...     print 'Layer "%s": %i %ss' % (layer.name, len(layer), layer.geom_type.name)
+    ...
+    Layer "cities": 3 Points
+
+The example output is from the cities data source, loaded above, which
+evidently contains one layer, called ``"cities"``, which contains three
+point features.  For simplicity, the examples below assume that you've 
+stored that layer in the variable ``layer``::
+
+    >>> layer = ds[0]
+
+.. attribute:: name
+
+Returns the name of this layer in the data source.
+
+    >>> layer.name
+    'cities'
+
+.. attribute:: num_feat
+
+Returns the number of features in the layer.  Same as ``len(layer)``::
+
+    >>> layer.num_feat
+    3
+
+.. attribute:: geom_type
+
+Returns the geometry type of the layer, as an ``OGRGeomType`` object
+(see below)::
+
+    >>> layer.geom_type.name
+    'Point'
+
+attribute:: get_geoms
+
+A method that returns a list containing the geometry of each feature
+in the layer.  If the optional argument ``geos`` is set to ``True``
+then the geometries are converted to GEOS geometry objects.
+Otherwise, they are returned as ``OGRGeometry`` objects (see below)::
+
+    >>> [pt.tuple for pt in layer.get_geoms()]
+    [(-104.609252, 38.255001), (-95.23506, 38.971823), (-95.363151, 29.763374)]
+
+.. attribute:: num_fields
+
+Returns the number of fields in the layer, i.e the number of fields of
+data associated with each feature in the layer::
+
+    >>> layer.num_fields
+    4
+
+.. attribute:: fields
+
+Returns a list of the names of each of the fields in this layer::
+
+    >>> layer.fields
+    ['Name', 'Population', 'Density', 'Created']
+
+.. attribute field_types
+
+Returns a list of the data types of each of the fields in this layer.
+These are subclasses of ``Field``, discussed below::
+
+    >>> [ft.__name__ for ft in layer.field_types]
+    ['OFTString', 'OFTReal', 'OFTReal', 'OFTDate']
+
+.. method:: get_fields()
+
+A method that returns a list of the values of a given field for each
+feature in the layer::
+
+    >>> layer.get_fields('Name')
+    ['Pueblo', 'Lawrence', 'Houston']
+
+.. attribute:: field_widths
+
+Returns a list of the maximum field widths for each of the fields in
+this layer::
+
+    >>> layer.field_widths
+    [80, 11, 24, 10]
+
+.. attribute:: field_precisions
+
+Returns a list of the numeric precisions for each of the fields in
+this layer.  This is meaningless (and set to zero) for non-numeric 
+fields::
+
+    >>> layer.field_precisions
+    [0, 0, 15, 0]
+
+.. attribute:: extent
+
+Returns the spatial extent of this layer, as an ``Envelope`` object (see below)::
+
+    >>> layer.extent.tuple
+    (-104.609252, 29.763374, -95.23506, 38.971823)
+
+.. attribute:: srs
+
+Returns the spatial reference system used in this layer, as a
+``SpatialReference`` object (see below)::
+
+    >>> layer.srs.name
+    'GCS_WGS_1984'
+
+``Feature``
+-----------
+
+``Feature`` wraps an OGR feature.  You never create a ``Feature``
+object directly.  Instead, you retrieve them from a ``Layer`` object.
+Each feature consists of a geometry and a set of fields containing
+additional properties.  The geometry of a field is accessible via its
+``geom`` property, which returns an ``OGRGeometry`` object (discussed
+below).  A ``Feature`` behaves like a standard Python container for
+its fields, which it returns as ``Field`` objects: you can access a
+field directly by its index or name, or you can iterate over a
+feature's fields, e.g. in a ``for`` loop.
+
+.. attribute:: geom
+
+Returns the geometry for this feature, as an ``OGRGeometry`` object::
+
+    >>> city.geom.tuple
+    (-104.609252, 38.255001)
+
+.. attribute:: get
+
+A method that returns the value of the given field (specified by name)
+for this feature, **not** a ``Field`` wrapper object::
+
+    >>> city.get('Population')
+    102121
+
+.. attribute:: geom_type
+
+Returns the type of geometry for this feature, as an ``OGRGeomType``
+object.  This will be the same for all features in a given layer, and
+is equivalent to the ``geom_type`` property of the ``Layer`` object
+itself.
+
+.. attribute:: num_fields
+
+Returns the number of fields of data associated with the feature.
+This will be the same for all features in a given layer, and is
+equivalent to the ``num_fields`` property of the ``Layer`` object
+itself.
+
+.. attribute:: fields
+
+Returns a list of the names of the fields of data associated with the
+feature.  This will be the same for all features in a given layer, and
+is equivalent to the ``fields`` property of the ``Layer`` object
+itself.
+
+.. attribute:: fid
+
+Returns the feature identifier within the layer::
+
+    >>> city.fid
+    0
+
+.. attribute:: layer_name
+
+Returns the name of the layer that the feature came from.  This will
+be the same for all features in a given layer::
+
+    >>> city.layer_name
+    'cities'
+
+.. attribute:: index
+
+A method that returns the index of the given field name.  This will be
+the same for all features in a given layer::
+
+    >>> city.index('Population')
+    1
+
+``Field``
+---------
+
+.. attribute:: name
+
+Returns the name of this field::
+
+    >>> city['Name'].name
+    'Name'
+
+.. attribute:: type
+
+Returns the OGR type of this field, as an integer.  The
+``FIELD_CLASSES`` dictionary maps these values onto 
+subclasses of ``Field``::
+
+    >>> city['Density'].type
+    2
+
+.. attribute:: type_name
+
+Returns a string with the name of the data type of this field::
+
+    >>> city['Name'].type_name
+    'String'
+
+.. attribute:: value
+
+Returns the value of this field.  The ``Field`` class itself 
+returns the value as a string, but each subclass returns the 
+value in the most appropriate form::
+
+    >>> city['Population'].value
+    102121
+
+.. attribute:: width
+
+Returns the width of this field::
+
+    >>> city['Name'].width
+    80
+
+.. attribute:: precision
+
+Returns the numeric precision of this field.  This is meaningless (and
+set to zero) for non-numeric fields::
+
+    >>> city['Density'].precision
+    15
+
+.. attribute:: as_double
+
+Returns the value of the field as a double (float)::
+
+    >>> city['Density'].as_double()
+    874.7
+
+.. attribute:: as_int
+
+Returns the value of the field as an integer::
+
+    >>> city['Population'].as_int()
+    102121
+
+.. attribute:: as_string
+
+Returns the value of the field as a string::
+
+    >>> city['Name'].as_string()
+    'Pueblo'
+
+.. attribute:: as_datetime
+
+Returns the value of the field as a tuple of date and time components::
+
+    >>> city['Created'].as_datetime()
+    (c_long(1999), c_long(5), c_long(23), c_long(0), c_long(0), c_long(0), c_long(0))
+
+.. attribute:: Driver
+
+``Driver`` is used internally to wrap an OGR data source driver.
+
+
+Geometries
+==========
+
+.. _ogrgeometry:
+
+.. attribute:: OGRGeometry
+
+``OGRGeometry`` is a wrapper for the OGR `Geometry`__ class.
+``OGRGeometry`` objects can be instantiated from a string containing a
+geometry object in WKT or HEX WKB format, a ``buffer`` containing WKB
+data, or an ``OGRGeomType`` object.  They are also returned when
+reading geometry data from OGR data sources via a ``DataSource``
+object.
+
+__ http://www.gdal.org/ogr/classOGRGeometry.html
+
+``OGRGeometry`` objects share some functionality with ``GEOSGeometry``
+objects.  ``OGRGeometry`` objects are thin wrappers around OGR
+geometry objects, and so they allow for more efficient access to data
+when using ``DataSource``.  Also, unlike its GEOS counterpart,
+``OGRGeometry`` supports spatial reference systems and their
+transformation::
+
+    >>> from django.contrib.gis.gdal import OGRGeometry
+    >>> polygon = OGRGeometry('POLYGON((0 0, 5 0, 5 5, 0 5))')
+
+.. attribute:: dimension
+
+Returns the number of coordinated dimensions of the geometry, i.e. 0
+for points, 1 for lines, and so forth::
+
+    >> polygon.dimension
+    2
+
+.. attribute:: geom_count
+
+Returns the number of elements in this geometry::
+
+    >>> polygon.geom_count
+    1
+
+.. attribute:: point_count
+.. attribute:: num_points
+.. attribute:: num_coords
+
+These identical properties each return the number of points used to
+describe this geometry::
+
+    >>> polygon.point_count
+    4
+
+.. attribute:: geom_type
+
+Returns the type of this geometry, as an ``OGRGeomType`` object.
+
+.. attribute:: geom_name
+
+Returns the name of the type of this geometry::
+
+    >>> polygon.geom_name
+    'POLYGON'
+
+.. attribute:: area
+
+Returns the area of this geometry, or 0 for geometries that do not
+contain an area::
+
+    >>> polygon.area
+    25.0
+
+.. attribute:: envelope
+
+Returns the envelope of this geometry, as an ``Envelope`` object.
+
+.. attribute:: extent
+
+Returns the envelope of this geometry as a 4-tuple, instead of as an
+``Envelope`` object::
+
+    >>> point.extent
+    (0.0, 0.0, 5.0, 5.0)
+
+.. attribute:: srs
+
+This property controls the spatial reference for this geometry, or
+None if no spatial reference system has been assigned to it.  You
+can get or set this property as a ``SpatialReference`` object::
+
+    >>> city.geom.srs.name
+    'GCS_WGS_1984'
+
+.. attribute:: srid
+
+This property controls the spatial reference for this geometry, or
+None if no spatial reference system has been assigned to it.  You
+can get or set this property as an integer ID.
+
+.. attribute:: geos
+
+Returns a ``GEOSGeometry`` object corresponding to this geometry.
+
+.. attribute:: gml
+
+Returns a string representation of this geometry in GML format::
+
+    >>> OGRGeometry('POINT(1 2)').gml
+    '<gml:Point><gml:coordinates>1,2</gml:coordinates></gml:Point>'
+
+.. attribute:: hex
+
+Returns a string representation of this geometry in HEX WKB format::
+
+    >>> OGRGeometry('POINT(1 2)').hex
+    '0101000000000000000000F03F0000000000000040'
+
+.. attribute:: json
+
+Returns a string representation of this geometry in JSON format::
+
+    >>> OGRGeometry('POINT(1 2)').hex
+    '{ "type": "Point", "coordinates": [ 1.000000, 2.000000 ] }'
+
+.. attribute:: wkb_size
+
+Returns the size of the WKB buffer needed to hold a WKB representation
+of this geometry::
+
+    >>> OGRGeometry('POINT(1 2)').wkb_size
+    21
+
+.. attribute:: wkb
+
+Returns a ``buffer`` containing a WKB representation of this geometry.
+
+.. attribute:: wkt
+
+Returns a string representation of this geometry in WKT format.
+
+.. function:: clone
+
+Clones this geometry object.
+
+.. function:: close_rings
+
+If there are any rings within this geometry that have not been closed,
+this routine will do so by adding the starting point to the end::
+
+    >>> triangle = OGRGeometry('LINEARRING (0 0,0 1,1 0)')
+    >>> triangle.close_rings()
+    >>> triangle.wkt
+    'LINEARRING (0 0,0 1,1 0,0 0)'
+
+.. function:: transform
+
+Transforms this geometry to a different spatial reference system.  May
+take a ``CoordTransform`` object, a ``SpatialReference`` object, a WKT
+or PROJ.4 string, or an integer SRID.  By default nothing is returned
+and the geometry is transformed in-place.  However, if the `clone`
+argument is set to ``True`` then a transformed clone of this geometry
+will be returned instead.
+
+.. function:: intersects
+
+Returns ``True`` if this geometry intersects the other, otherwise returns
+``False``.
+
+.. function:: equals
+
+Returns ``True`` if this geometry is equivalent to the other, otherwise returns
+``False``.
+
+.. function:: disjoint
+
+Returns ``True`` if this geometry is spatially disjoint to (i.e. does
+not intersect) the other, otherwise returns
+``False``.
+
+.. function:: touches
+
+Returns ``True`` if this geometry touches the other, otherwise returns
+``False``.
+
+.. function:: crosses
+
+Returns ``True`` if this geometry crosses the other, otherwise returns
+``False``.
+
+.. function:: within
+
+Returns ``True`` if this geometry is contained within the other, otherwise returns
+``False``.
+
+.. function:: contains
+
+Returns ``True`` if this geometry contains the other, otherwise returns
+``False``.
+
+.. function:: overlaps
+
+Returns ``True`` if this geometry overlaps the other, otherwise returns
+``False``.
+
+.. function:: boundary
+
+The boundary of this geometry, as a new ``OGRGeometry`` object.
+
+.. attribute:: convex_hull
+
+The smallest convex polygon that contains this geometry, as a new
+``OGRGeometry`` object.
+
+.. function:: difference
+
+Returns the region consisting of the difference of this geometry and
+the other, as a new ``OGRGeometry`` object.
+
+.. function:: intersection
+
+Returns the region consisting of the intersection of this geometry and
+the other, as a new ``OGRGeometry`` object.
+
+.. function:: sym_difference
+
+Returns the region consisting of the symmetric difference of this
+geometry and the other, as a new ``OGRGeometry`` object.
+
+.. function:: union
+
+Returns the region consisting of the union of this geometry and
+the other, as a new ``OGRGeometry`` object.
+
+.. attribute:: x
+
+Returns the X coordinate of a point geometry, or a list of X
+coordinates of a LineString geometry.  Not applicable to other
+geometry types.
+
+    >>> OGRGeometry('POINT (1 2)').x
+    1.0
+    >>> OGRGeometry('LINESTRING (1 2,3 4)').x
+    [1.0, 3.0]
+
+.. attribute:: y
+
+Returns the X coordinate of a point geometry, or a list of X
+coordinates of a LineString geometry.  Not applicable to other
+geometry types.
+
+    >>> OGRGeometry('POINT (1 2)').y
+    2.0
+    >>> OGRGeometry('LINESTRING (1 2,3 4)').y
+    [2.0, 4.0]
+
+.. attribute:: z
+
+Returns the Z coordinate of a point geometry, or a list of Z
+coordinates of a LineString geometry.  Returns ``None`` if the 
+geometry does not have Z coordinates.  Not applicable to other
+geometry types::
+
+    >>> OGRGeometry('POINT (1 2 3)').z
+    3.0
+    >>> OGRGeometry('LINESTRING (1 2 3,4 5 6)').z
+    [3.0, 6.0]
+
+.. attribute:: tuple
+.. attribute:: coords
+
+Returns the coordinates of a point geometry as a tuple, the
+coordinates of a line geometry as a tuple of tuples, and so forth::
+
+    >>> OGRGeometry('POINT (1 2)').tuple
+    (1.0, 2.0)
+    >>> OGRGeometry('LINESTRING (1 2,3 4)').tuple
+    ((1.0, 2.0), (3.0, 4.0))
+
+.. function:: add
+
+Adds a geometry to this geometry collection.  Not applicable to other
+geometry types.
+
+.. function:: shell
+.. function:: exterior_ring
+
+Returns the shell or exterior ring of this polygon, as a ``LinearRing``
+geometry.  Not applicable to other geometry types.
+
+.. function:: __len__
+
+Returns the number of points in a LineString, of the number of interior
+rings in a Polygon, or the number of geometries in a
+GeometryCollection.  Not applicable to other geometry types.
+
+.. function:: __iter__
+
+Iterates over the points in a LineString, of the interior rings in a
+Polygon, or the geometries in a GeometryCollection.  Not applicable to
+other geometry types.
+
+.. function:: __getitem__
+
+Returns the point at the specified index for this LineString, or the
+interior ring at the specified index for this Polygon, or the geometry
+at the specified index for this GeometryCollection.  Not applicable to
+other geometry types.
+
+``LineString``
+--------------
+
+A subclass of ``OGRGeometry`` representing a line string.
+
+.. function:: shell
+
+.. function:: point_count
+
+.. function:: centroid
+
+.. function:: OGRGeomType
+
+The ``OGRGeomType`` class is makes it easy to specify an OGR geometry
+type in any of several ways::
+
+    >>> from django.contrib.gis.gdal import OGRGeomType
+    >>> gt1 = OGRGeomType(3)             # Using an integer for the type
+    >>> gt2 = OGRGeomType('Polygon')     # Using a string
+    >>> gt3 = OGRGeomType('POLYGON')     # It's case-insensitive
+    >>> print gt1 == 3, gt1 == 'Polygon' # Equivalence works w/non-OGRGeomType objects
+    True True
+
+.. attribute:: name
+
+Returns a short-hand string form of the OGR Geometry type::
+
+    >>> gt1.name
+    'Polygon'
+
+.. attribute:: django
+
+Returns the Django field type (a subclass of GeometryField) to use for
+storing this OGR type, or ``None`` if there is no appropriate Django
+type::
+
+    >>> gt1.django
+    'PolygonField'
+
+.. _spatialreference:
+
+``SpatialReference``
+====================
+
+.. function:: attr_value
+
+.. function:: auth_name
+
+.. function:: auth_code
+
+.. function:: clone
+
+.. function:: identify_epsg
+
+.. function:: validate
+
+.. function:: name
+
+.. function:: srid
+
+.. function:: linear_name
+
+.. function:: linear_units
+
+.. function:: angular_name
+
+.. function:: angular_units
+
+.. function:: units
+
+.. function:: ellisoid
+
+.. function:: semi_major
+
+.. function:: semi_minor
+
+.. function:: inverse_flattening
+
+.. function:: geographic
+
+.. function:: local
+
+.. function:: projected
+
+.. function:: import_wkt
+
+.. function:: import_proj
+
+.. function:: import_epsg
+
+.. function:: import_xml
+
+.. function:: wkt
+
+.. function:: pretty_wkt
+
+.. function:: proj
+.. function:: proj4
+
+.. function:: xml
+
+.. function:: to_esri
+
+.. function:: from_esri
+
+.. function:: CoordTransform
+
+``CoordTransform`` represents a coordinate system transform.  It is
+initialized with two ``SpatialReference``, representing the source and
+target coordinate systems, respectively.
+
+.. function:: Envelope
+
+``Envelope`` represents an OGR Envelope structure that contains the
+minimum and maximum X, Y coordinates for a rectangle bounding box.
+The naming of the variables is compatible with the OGR Envelope
+structure.
+
+.. function:: min_x
+
+The value of the minimum X coordinate.
+
+.. function:: min_y
+
+The value of the maximum X coordinate.
+
+.. function:: max_x
+
+The value of the minimum Y coordinate.
+
+.. function:: max_y
+
+The value of the maximum Y coordinate.
+
+.. function:: ur
+
+The upper-right coordinate, as a tuple.
+
+.. function:: ll
+
+The lower-left coordinate, as a tuple.
+
+.. function:: tuple
+
+A tuple representing the envelope.
+
+.. function:: wkt
+
+A string representing this envelope as a polygon in WKT format.
Index: docs/ref/contrib/gis/index.txt
===================================================================
--- docs/ref/contrib/gis/index.txt	(revision 0)
+++ docs/ref/contrib/gis/index.txt	(revision 0)
@@ -0,0 +1,26 @@
+.. _ref-contrib-gis:
+
+=========
+GeoDjango
+=========
+
+.. versionadded:: 1.0
+
+GeoDjango intends to be a world-class geographic web framework. Our goal is to make it as easy
+as possible to build GIS web applications and harness the power of spatially enabled data.
+
+.. toctree::
+   :maxdepth: 2
+
+   tutorial
+   install
+   model-api
+   db-api
+   geos
+   measure
+   gdal
+   utils
+   feeds
+   sitemaps
+   testing
+   deployment
Index: docs/ref/contrib/gis/model-api.txt
===================================================================
--- docs/ref/contrib/gis/model-api.txt	(revision 0)
+++ docs/ref/contrib/gis/model-api.txt	(revision 0)
@@ -0,0 +1,146 @@
+===================
+GeoDjango Model API
+===================
+
+This document explores the details of the GeoDjango Model API.  Throughout this
+section, we'll be using the following geographic model of a `ZIP code`__ as our 
+example::
+
+    from django.contrib.gis.db import models
+    
+    class Zipcode(models.Model):
+        code = models.CharField(max_length=5)
+        poly = models.PolygonField()
+        objects = models.GeoManager()
+
+__ http://en.wikipedia.org/wiki/ZIP_code
+
+Geometry Field Types
+====================
+
+The following geometry fields are available:
+
+    * ``PointField``
+    * ``LineStringField``
+    * ``PolygonField``
+    * ``MultiPointField``
+    * ``MultiLineStringField``
+    * ``MultiPolygonField``
+    * ``GeometryCollectionField``
+
+Each of these fields correspond with OpenGIS Simple Features [#]_.
+
+Geometry Field Options
+----------------------
+
+In addition to the regular `field options`__ available for Django model fields, 
+geometry fields have the following additional options:
+
+======================  ===================================================
+Argument                Description
+======================  ===================================================
+``srid``                Sets the SRID [#]_ (Spatial Reference System 
+                        Identity) of the geometry field to the given value.
+                        Defaults to 4326 (also known as `WGS84`__, units 
+                        are in degrees of longitude and latitude).
+
+``dim``			*New in version 1.2*
+
+                        Sets the coordinate dimension for the geometry
+                        field.  By default, it is 2 (for two-dimensional
+			geometries), but may be set to 3 if GeoDjango
+                        supports 3D geometries for your spatial backend and
+			GEOS 3.1 is installed.
+
+``spatial_index``       Defaults to True.  Creates a spatial index for the 
+                        given geometry. Please note that this is different
+                        from the ``db_index`` field option because 
+                        spatial indexes are created in a different manner 
+                        than regular database indexes. 
+======================  ===================================================
+
+__ http://docs.djangoproject.com/en/dev/ref/models/fields/#field-options
+__ http://en.wikipedia.org/wiki/WGS84
+
+Selecting an SRID
+^^^^^^^^^^^^^^^^^
+
+Choosing an appropriate SRID for your model is an important decision that the
+developer should consider carefully.  The SRID is an integer specifier that 
+corresponds to the projection system that will be used to interpret the data
+in the spatial database. [#]_  Projection systems give the context to the
+coordinates that specify a location.  Although the details of `geodesy`__ are
+beyond the scope of this documentation, the general problem is that the earth
+is spherical and representations of the earth (e.g., paper maps, web maps)
+are not.
+
+Most people are familiar with using latitude and longitude to reference a
+location on the earth's surface.  However, latitude and longitude are angles,
+not distances. [#]_  In other words, while the shortest path between two points on
+a flat surface is a straight line, the shortest path between two points on a curved
+surface (such as the earth) is an *arc* of a `great circle`__. [#]_  Thus,
+additional computation is required to obtain distances in planar units (e.g., 
+kilometers and miles).  Using a geographic coordinate system may introduce
+complications for the developer later on.  For example, PostGIS does not
+have the capability to perform distance calculations between non-point
+geometries using geographic coordinate systems, e.g., constructing a query to 
+find all points within 5 miles of a county boundary stored as WGS84. [#]_
+
+Portions of the earth's surface may projected onto a two-dimensional, or 
+Cartesian, plane.  Projected coordinate systems are especially convenient
+for region-specific applications, e.g., if you know that your database will
+only cover geometries in `North Kansas`__, then you may consider using projection 
+system specific to that region.  Moreover, projected coordinate systems are 
+defined in Cartesian units (such as meters or feet), easing distance 
+calculations.
+
+Additional Resources:
+
+* `spatialreference.org`__: A Django-powered database of spatial reference 
+  systems.
+* `The State Plane Coordinate System`__: A website covering the various
+  projection systems used in the United States.  Much of the U.S. spatial
+  data encountered will be in one of these coordinate systems rather than
+  in a geographic coordinate system such as WGS84.
+
+__ http://en.wikipedia.org/wiki/Geodesy
+__ http://en.wikipedia.org/wiki/Great_circle
+__ http://www.spatialreference.org/ref/epsg/2796/
+__ http://spatialreference.org/
+__ http://welcome.warnercnr.colostate.edu/class_info/nr502/lg3/datums_coordinates/spcs.html
+
+``GeoManager``
+==============
+
+In order to conduct geographic queries, each geographic model requires 
+a ``GeoManager`` model manager.  This manager allows for the proper SQL
+construction for geographic queries; thus, without it, all geographic filters 
+will fail.  It should also be noted that ``GeoManager`` is required even if the
+model does not have a geographic field itself, e.g., in the case of a 
+``ForeignKey`` relation to a model with a geographic field.  For example, 
+if we had an ``Address`` model with a ``ForeignKey`` to our ``Zipcode`` 
+model::
+
+    from django.contrib.gis.db import models
+    from django.contrib.localflavor.us.models import USStateField
+
+    class Address(models.Model):
+        num = models.IntegerField()
+        street = models.CharField(max_length=100)
+        city = models.CharField(max_length=100)
+        state = USStateField()
+        zipcode = models.ForeignKey(Zipcode)
+        objects = models.GeoManager()
+
+The geographic manager is needed to do spatial queries on related ``Zipcode`` objects, 
+for example::
+
+    qs = Address.objects.filter(zipcode__poly__contains='POINT(-104.590948 38.319914)')
+
+.. rubric:: Footnotes
+.. [#] OpenGIS Consortium, Inc., `Simple Feature Specification For SQL <http://www.opengis.org/docs/99-049.pdf>`_, Document 99-049 (May 5, 1999).
+.. [#] *See id.* at Ch. 2.3.8, p. 39 (Geometry Values and Spatial Reference Systems).
+.. [#] Typically, SRID integer corresponds to an EPSG (`European Petroleum Survey Group <http://www.epsg.org>`_) identifier.  However, it may also be associated with custom projections defined in spatial database's spatial reference systems table.
+.. [#] Harvard Graduate School of Design, `An Overview of Geodesy and Geographic Referencing Systems <http://www.gsd.harvard.edu/gis/manual/projections/fundamentals/>`_.  This is an excellent resource for an overview of principles relating to geographic and Cartesian coordinate systems. 
+.. [#] Terry A. Slocum, Robert B. McMaster, Fritz C. Kessler, & Hugh H. Howard, *Thematic Cartography and Geographic Visualization* (Prentice Hall, 2nd edition), at Ch. 7.1.3.
+.. [#] This isn't impossible using GeoDjango; you could for example, take a known point in a projected coordinate system, buffer it to the appropriate radius, and then perform an intersection operation with the buffer transformed to the geographic coordinate system.
Index: docs/ref/contrib/gis/testing.txt
===================================================================
--- docs/ref/contrib/gis/testing.txt	(revision 0)
+++ docs/ref/contrib/gis/testing.txt	(revision 0)
@@ -0,0 +1,170 @@
+======================
+Testing GeoDjango Apps
+======================
+
+Creating a spatial database may require extra steps.  To accommodate this, 
+GeoDjango includes a test runner that will scaffold a spatial database 
+automatically.  To have your tests utilize the runner, just configure 
+your ``TEST_RUNNER`` in your settings like the following::
+
+    TEST_RUNNER='django.contrib.gis.tests.run_tests'
+
+If you want to run GeoDjango's test suite (do *not* use for testing your
+applications) then the runner would be configured like so::
+
+    TEST_RUNNER='django.contrib.gis.tests.run_gis_tests'
+
+.. note::
+
+    In order to create a spatial database, the ``DATABASE_USER`` setting
+    (or ``TEST_DATABASE_USER``, if optionally defined on Oracle) requires
+    elevated privileges.  When using PostGIS or MySQL, the database user 
+    must have at least the ability to create databases.  When testing on Oracle,
+    the user should be a superuser.
+
+Besides configuring the ``TEST_RUNNER`` setting, there are other options
+to consider depending on your spatial backend (no additional
+options or configuration instructions for the Oracle or MySQL spatial
+backends).
+
+PostGIS
+=======
+
+.. note::
+
+    In addition to setting ``TEST_RUNNER`` as described above, the 
+    recommended way to test GeoDjango applications with PostGIS
+    is to set :ref:`postgis_template` with the name of your
+    `spatial database template`_.
+
+.. _spatial database template: install.html#creating-a-spatial-database-template-for-postgis
+
+Settings
+--------
+
+``POSTGIS_SQL_PATH``
+^^^^^^^^^^^^^^^^^^^^
+
+If not using the ``POSTGIS_TEMPLATE`` setting, the GeoDjango test runner
+assumes that the PostGIS SQL files (``lwpostgis.sql`` and 
+``spatial_ref_sys.sql``) are installed in the directory specified by
+the following command::
+
+    $ pg_config --sharedir 
+
+If that command cannot be executed, the test runner will default to
+``/usr/local/share``, unless this setting is configured with a 
+different location.  For example, some PostGIS packages for Ubuntu
+put the files in a nonstandard location, and placing this in the
+settings would allow GeoDjango to find the files::
+
+    POSTGIS_SQL_PATH='/usr/share/postgresql-8.3-postgis'
+
+.. _postgis_template:
+
+``POSTGIS_TEMPLATE``
+^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 1.1
+
+If you have a PostGIS template already, then just configure with the
+name of the template in your settings, for example::
+
+    POSTGIS_TEMPLATE='template_postgis'
+
+``POSTGIS_VERSION``
+^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 1.1
+
+When GeoDjango's spatial backend initializes on PostGIS, it has to perform
+a SQL query to determine the version.  Setting the version manually
+prevents this query to the database::
+
+    POSTGIS_VERSION=('1.3.6', 1, 3, 6)
+
+Obtaining Sufficient Privileges
+-------------------------------
+
+Depending on your configuration, this section describes several methods to
+configure a database user with sufficient privileges to run tests for
+GeoDjango applications on PostgreSQL.  If your `spatial database template`_
+was created like in the instructions, then your testing database user
+only needs to have the ability to create databases.  In other configurations,
+you may be required to use a superuser.
+
+Create Database User
+^^^^^^^^^^^^^^^^^^^^
+To make database user with the ability to create databases, use the
+following command::
+
+    $ createuser --createdb -R -S <user_name>
+
+The ``-R -S`` flags indicate that we do not want the user to have the ability
+to create additional users (roles) or to be a superuser, respectively.
+
+Alternatively, you may alter an existing user's role from the SQL shell
+(assuming this is done from an existing superuser account)::
+
+    postgres# ALTER ROLE <user_name> CREATEDB NOSUPERUSER NOCREATEROLE;
+
+Create Database Superuser
+^^^^^^^^^^^^^^^^^^^^^^^^^
+This may be done at the time the user is created, for example::
+
+    $ createuser --superuser <user_name>
+
+Or you may alter the user's role from the SQL shell (assuming this
+is done from an existing superuser account)::
+
+    postgres# ALTER ROLE <user_name> SUPERUSER;
+
+
+Create Local PostgreSQL Database
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+1. Initialize database: ``initdb -D /path/to/user/db``
+
+2. If there's already a Postgres instance on the machine, it will need
+   to use a different TCP port than 5432. Edit ``postgresql.conf`` (in
+   ``/path/to/user/db``) to change the database port (e.g. ``port = 5433``).
+
+3. Start this database ``pg_ctl -D /path/to/user/db start``
+
+Windows
+-------
+On Windows platforms the pgAdmin III utility may also be used as
+a simple way to add superuser privileges to your database user.
+
+By default, the PostGIS installer on Windows includes a template
+spatial database.  Take advantage of it by adding this to your
+settings::
+
+   POSTGIS_TEMPLATE='template_postgis'
+
+SpatiaLite
+==========
+.. versionadded:: 1.1
+
+You will need to download the `initialization SQL`__ script for SpatiaLite::
+
+    $ wget http://www.gaia-gis.it/spatialite/init_spatialite-2.3.zip
+    $ unzip init_spatialite-2.3.zip
+
+If ``init_spatialite-2.3.sql`` is in the same path as your project's ``manage.py``
+script and your ``TEST_RUNNER`` is set, then all you have to do is::
+
+    $ ./manage.py test 
+
+Settings
+--------
+
+``SPATIALITE_SQL``
+^^^^^^^^^^^^^^^^^^
+.. versionadded:: 1.1
+
+By default, the GeoDjango test runner looks for the SpatiaLite SQL in the
+same directory where it was invoked (by default the same directory where
+``manage.py`` is located).  If you want to use a different location, then
+you may add the following to your settings::
+
+    SPATIALITE_SQL='/path/to/init_spatialite-2.3.sql'
+
+__ http://www.gaia-gis.it/spatialite/init_spatialite-2.3.zip
Index: docs/ref/contrib/gis/deployment.txt
===================================================================
--- docs/ref/contrib/gis/deployment.txt	(revision 0)
+++ docs/ref/contrib/gis/deployment.txt	(revision 0)
@@ -0,0 +1,102 @@
+===================
+Deploying GeoDjango
+===================
+
+.. warning::
+
+    GeoDjango uses the GEOS and GDAL geospatial libraries which are
+    not thread safe at this time.  Thus, it is *highly* recommended
+    to not use threading when deploying -- in other words, use a 
+    prefork version of Apache or the prefork method when using FastCGI
+    through another web server.
+
+Apache
+======
+In this section there are some example ``VirtualHost`` directives for 
+when deploying using either ``mod_python`` or ``mod_wsgi``.  At this
+time, we recommend ``mod_wsgi``, as it is now officially recommended 
+way to deploy Django applications with Apache.  Moreover, if
+``mod_python`` is used, then a prefork version of Apache must also be
+used.  As long as ``mod_wsgi`` is configured correctly, it does not
+matter whether the version of Apache is prefork or worker.
+
+.. note::
+
+    The ``Alias`` and ``Directory`` configurations in the the examples
+    below use an example path to a system-wide installation folder of Django.  
+    Substitute in an appropriate location, if necessary, as it may be
+    different than the path on your system.
+
+``mod_wsgi``
+------------
+
+Example::
+
+    <VirtualHost *:80>
+      WSGIDaemonProcess geodjango user=geo group=geo processes=5 threads=1
+      WSGIProcessGroup geodjango
+      WSGIScriptAlias / /home/geo/geodjango/world.wsgi
+  
+      Alias /media/ "/usr/lib/python2.5/site-packages/django/contrib/admin/media/"
+      <Directory "/usr/lib/python2.5/site-packages/django/contrib/admin/media/">
+        Order allow,deny
+        Options Indexes
+        Allow from all
+        IndexOptions FancyIndexing
+      </Directory>
+    
+    </VirtualHost>
+
+.. warning::
+
+    If the ``WSGIDaemonProcess`` attribute ``threads`` is not set to ``1``, then
+    Apache may crash when running your GeoDjango application.  Increase the 
+    number of ``processes`` instead.
+
+For more information, please consult Django's `mod_wsgi documentation`__.
+
+__ http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/
+
+
+``mod_python``
+--------------
+
+Example::
+
+    <VirtualHost *:80>
+    
+      <Location "/">
+        SetHandler mod_python
+        PythonHandler django.core.handlers.modpython
+        SetEnv DJANGO_SETTINGS_MODULE world.settings
+        PythonDebug On
+        PythonPath "['/var/www/apps'] + sys.path"
+      </Location>
+    
+      Alias /media/ "/usr/lib/python2.5/site-packages/django/contrib/admin/media/"
+      <Location "/media">
+        SetHandler None
+      </Location>
+    
+    </VirtualHost>
+
+.. warning::
+
+   When using ``mod_python`` you must be using a prefork version of Apache, or
+   else your GeoDjango application may crash Apache.
+
+For more information, please consult Django's `mod_python documentation`__.
+
+__ http://docs.djangoproject.com/en/dev/howto/deployment/modpython/
+
+Lighttpd
+========
+
+FastCGI
+-------
+
+Nginx
+=====
+
+FastCGI
+-------
Index: docs/ref/contrib/gis/create_template_postgis-debian.sh
===================================================================
--- docs/ref/contrib/gis/create_template_postgis-debian.sh	(revision 0)
+++ docs/ref/contrib/gis/create_template_postgis-debian.sh	(revision 0)
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+POSTGIS_SQL_PATH=/usr/share/postgresql-8.3-postgis
+createdb -E UTF8 template_postgis # Create the template spatial database.
+createlang -d template_postgis plpgsql # Adding PLPGSQL language support.
+psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';"
+psql -d template_postgis -f $POSTGIS_SQL_PATH/lwpostgis.sql # Loading the PostGIS SQL routines
+psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql
+psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables.
+psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"

Property changes on: docs/ref/contrib/gis/create_template_postgis-debian.sh
___________________________________________________________________
Name: svn:executable
   + *

Index: docs/ref/contrib/gis/sitemaps.txt
===================================================================
--- docs/ref/contrib/gis/sitemaps.txt	(revision 0)
+++ docs/ref/contrib/gis/sitemaps.txt	(revision 0)
@@ -0,0 +1,27 @@
+===================
+Geographic Sitemaps
+===================
+
+Google's sitemap protocol has been recently extended to support geospatial
+content. [#]_   This includes the addition of the ``<url>`` child element
+``<geo:geo>``, which tells Google that the content located at the URL is
+geographic in nature. [#]_ 
+
+Example
+=======
+
+Reference
+=========
+
+``KMLSitemap``
+--------------
+
+``KMZSitemap``
+--------------
+
+``GeoRSSSitemap``
+-----------------
+
+.. rubric:: Footnotes
+.. [#] Google, Inc., `What is a Geo Sitemap? <http://www.google.com/support/webmasters/bin/answer.py?answer=94554>`_.
+.. [#] Google, Inc., `Submit Your Geo Content to Google <http://code.google.com/apis/kml/documentation/kmlSearch.html>`_.
Index: docs/ref/contrib/gis/feeds.txt
===================================================================
--- docs/ref/contrib/gis/feeds.txt	(revision 0)
+++ docs/ref/contrib/gis/feeds.txt	(revision 0)
@@ -0,0 +1,93 @@
+================
+Geographic Feeds
+================
+
+GeoDjango has its own ``Feed`` subclass that may embed location information
+in RSS/Atom feeds formatted according to either the `Simple GeoRSS`__ or 
+`W3C Geo`_ standards.  Because GeoDjango's syndication API is a superset of
+Django's, please consult `Django's syndication documentation`__ for details
+on general usage.
+
+.. _W3C Geo: http://www.w3.org/2003/01/geo/
+
+__ http://georss.org/1.0#simple
+__ http://docs.djangoproject.com/en/dev/ref/contrib/syndication/
+
+Example
+=======
+
+API Reference
+=============
+
+``Feed`` Subclass
+-----------------
+
+In addition to methods provided by `base class`__ GeoDjango's ``Feed``
+class (from ``django.contrib.gis.feeds``) provides the following overrides.
+Note that these overrides may be done in multiple ways::
+
+    from django.contrib.gis.feeds import Feed
+
+    class MyFeed(Feed):
+
+         # First, as a class attribute.
+         geometry = ...
+         item_geometry = ...
+
+         # Also a function with no arguments
+         def geometry(self):
+             ...
+
+         def item_geometry(self):
+             ...
+
+         # And as a function with a single argument
+         def geometry(self, obj):
+             ...
+
+         def item_geometry(self, item):
+             ...
+
+__ http://docs.djangoproject.com/en/dev/ref/contrib/syndication/#django.contrib.syndication.django.contrib.syndication.feeds.Feed
+
+``Feed.geometry(obj)``
+^^^^^^^^^^^^^^^^^^^^^^
+
+Takes the object returned by ``get_object()`` and returns the *feed's*
+geometry.  Typically this is a ``GEOSGeometry`` instance, or can be a
+tuple to represent a point or a box.  For example::
+
+    class ZipcodeFeed(Feed):
+
+        def geometry(self, obj):
+            # Can also return: `obj.poly`, and `obj.poly.centroid`.
+            return obj.poly.extent # tuple like: (X0, Y0, X1, Y1).
+
+``Feed.item_geometry(item)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Set this to return the geometry for each *item* in the feed.  This
+can be a ``GEOSGeometry`` instance, or a tuple that represents a
+point coordinate or bounding box.  For example::
+
+    class ZipcodeFeed(Feed):
+
+        def item_geometry(self, obj):
+	    # Returns the polygon.
+            return obj.poly
+
+``SyndicationFeed`` Subclasses
+------------------------------
+
+``GeoRSSFeed``
+^^^^^^^^^^^^^^
+
+``GeoAtom1Feed``
+^^^^^^^^^^^^^^^^
+
+``W3CGeoFeed``
+^^^^^^^^^^^^^^
+
+.. note::
+
+    `W3C Geo`_ formatted feeds only support point geometries.
Index: docs/ref/contrib/gis/layermapping.txt
===================================================================
--- docs/ref/contrib/gis/layermapping.txt	(revision 0)
+++ docs/ref/contrib/gis/layermapping.txt	(revision 0)
@@ -0,0 +1,212 @@
+================
+``LayerMapping``
+================
+
+*Requirements:* The GDAL library must be installed.
+
+The LayerMapping class provides a way to map the contents of OGR
+vector files (e.g. shapefiles) to Geographic-enabled Django models.
+
+This grew out of the author's personal needs; specifically, the code 
+repetition that went into pulling geometries and fields out of an OGR 
+layer, converting to another coordinate system (e.g. WGS84), and 
+inserting into a GeoDjango model.
+
+Usage::
+
+    lm = LayerMapping(model, data_source, mapping, 
+                      [layer=LAYER, source_srs=SRS, encoding=ENCODING,
+                       transaction_mode=XMODE, transform=XFORM])
+    lm.save([fid_range=FID_RANGE, progress=PROGRESS, silent=SILENT,
+             step=STEP, stream=STREAM, strict=STRICT, verbose=VERBOSE])
+
+.. warning ::
+
+    GIS data sources, like shapefiles, may be very large.  If you find
+    that ``LayerMapping`` is using too much memory, set
+    ``DEBUG=False`` in your settings.  When ``DEBUG=True`` Django automatically
+    logs *every* SQL query -- thus, when SQL statements contain geometries, it is 
+    easy to consume more memory than usual.
+
+Example
+=======
+
+1. You need a GDAL-supported data source, like a shapefile (here we're using
+   a simple polygon shapefile, ``test_poly.shp``, with three features)::
+
+    >>> from django.contrib.gis.gdal import DataSource
+    >>> ds = DataSource('test_poly.shp')
+    >>> layer = ds[0]
+    >>> print layer.fields # Exploring the fields in the layer, we only want the 'str' field.
+    ['float', 'int', 'str']
+    >>> print len(layer) # getting the number of features in the layer (should be 3)
+    3
+    >>> print layer.geom_type # Should be 3 (a Polygon)
+    3
+    >>> print layer.srs # WGS84
+    GEOGCS["GCS_WGS_1984",
+        DATUM["WGS_1984",
+            SPHEROID["WGS_1984",6378137,298.257223563]],
+        PRIMEM["Greenwich",0],
+        UNIT["Degree",0.017453292519943295]]    
+
+2. Now we define our corresponding Django model (make sure to use syncdb)::
+
+    from django.contrib.gis.db import models
+
+    class TestGeo(models.Model):
+        name = models.CharField(max_length=25) # corresponds to the 'str' field
+        poly = models.PolygonField(srid=4269) # we want our model in a different SRID
+        objects = models.GeoManager()
+        def __str__(self):
+            return 'Name: %s' % self.name
+
+3. Use ``LayerMapping`` to extract all the features and place them in the database::
+
+    >>> from django.contrib.gis.utils import LayerMapping
+    >>> from geoapp.models import TestGeo
+    >>> mapping = {'name' : 'str', # The 'name' model field maps to the 'str' layer field.
+                   'poly' : 'POLYGON', # For geometry fields use OGC name.
+                   } # The mapping is a dictionary
+    >>> lm = LayerMapping(TestGeo, 'test_poly.shp', mapping) 
+    >>> lm.save(verbose=True) # Save the layermap, imports the data. 
+    Saved: Name: 1
+    Saved: Name: 2
+    Saved: Name: 3
+
+ LayerMapping just transformed the three geometries from the SHP file from their
+ source spatial reference system (WGS84) to the spatial reference system of
+ the GeoDjango model (NAD83).  If no spatial reference system is defined for
+ the layer, use the ``source_srs`` keyword with a SpatialReference object to
+ specify one.
+
+API Reference
+=============
+
+Initialization
+--------------
+
+The following are the arguments and keywords that may be used during
+instantiation of ``LayerMapping`` objects.
+
+=================  =========================================================
+Argument           Description
+=================  =========================================================
+``model``          The geographic model, *not* an instance.
+
+``data_source``    The path to the OGR-supported data source file
+                   (e.g., a shapefile).  Also accepts
+                   ``gdal.DataSource`` instances.
+
+``mapping``        A dictionary: keys are strings corresponding to
+                   the model field, and values correspond to
+                   string field names for the OGR feature, or if the
+                   model field is a geographic then it should
+                   correspond to the OGR geometry type,
+                   e.g., ``'POINT'``, ``'LINESTRING'``, ``'POLYGON'``.
+=================  =========================================================  
+
+=====================  =====================================================
+Keyword Arguments
+=====================  =====================================================  
+``layer``              The index of the layer to use from the Data Source 
+                       (defaults to 0)
+    
+``source_srs``         Use this to specify the source SRS manually (for 
+                       example, some shapefiles don't come with a '.prj' 
+                       file).  An integer SRID, WKT or PROJ.4 strings, and 
+                       ``SpatialReference`` objects are accepted.
+    
+``encoding``           Specifies the character set encoding of the strings 
+                       in the OGR data source.  For example, 'latin-1', 
+                       'utf-8', and 'cp437' are all valid encoding 
+                       parameters.
+    
+``transaction_mode``   May be 'commit_on_success' (default) or 
+                       'autocommit'.
+    
+``transform``          Setting this to False will disable coordinate 
+                       transformations.  In other words, geometries will
+                       be inserted into the database unmodified from their
+                       original state in the data source.
+    
+``unique``             Setting this to the name, or a tuple of names,
+                       from the given  model will create models unique
+                       only to the given name(s). Geometries will from 
+                       each feature will be added into the collection 
+                       associated with the unique model.  Forces 
+                       the transaction mode to be 'autocommit'.
+=====================  =====================================================  
+
+Keyword Arguments for ``save()``
+--------------------------------
+
+The ``save()`` method also accepts keywords.  These keywords are
+used for controlling output logging, error handling, and for importing
+specific feature ranges.
+
+===========================  =================================================
+Save Keyword Arguments       Description
+===========================  =================================================
+``fid_range``                May be set with a slice or tuple of 
+                             (begin, end) feature ID's to map from 
+                             the data source.  In other words, this
+                             keyword enables the user to selectively 
+                             import a subset range of features in the
+                             geographic data source.
+
+``progress``                 When this keyword is set, status information
+                             will be printed giving the number of features 
+                             processed and successfully saved.  By default, 
+                             progress information will be printed every 1000
+                             features processed, however, this default may 
+                             be overridden by setting this keyword with an 
+                             integer for the desired interval.
+
+``silent``                   By default, non-fatal error notifications are 
+                             printed to ``sys.stdout``, but this keyword may 
+                             be set to disable these notifications.
+
+``step``                     If set with an integer, transactions will 
+                             occur at every step interval. For example, if 
+                             ``step=1000``, a commit would occur after the 
+                             1,000th feature, the 2,000th feature etc.
+
+
+``stream``                   Status information will be written to this file 
+                             handle.  Defaults to using ``sys.stdout``, but 
+                             any object with a ``write`` method is supported.
+
+``strict``                   Execution of the model mapping will cease upon 
+                             the first error encountered.  The default value
+                             (``False``)
+                             behavior is to attempt to continue.
+
+``verbose``                  If set, information will be printed 
+                             subsequent to each model save 
+                             executed on the database.
+===========================  =================================================
+
+Troubleshooting
+===============
+
+Running out of memory
+---------------------
+
+As noted in the warning at the top of this section, Django stores all SQL
+queries when ``DEBUG=True``.  Set ``DEBUG=False`` in your settings, and this
+should stop excessive memory use when running ``LayerMapping`` scripts.
+
+MySQL: ``max_allowed_packet`` error
+-----------------------------------
+
+If you encounter the following error when using ``LayerMapping`` and MySQL::
+
+    OperationalError: (1153, "Got a packet bigger than 'max_allowed_packet' bytes")
+
+Then the solution is to increase the value of the ``max_allowed_packet``
+setting in your MySQL configuration.  For example, the default value may 
+be something low like one megabyte -- the setting may be modified in MySQL's
+configuration file (``my.cnf``) in the ``[mysqld]`` section::
+
+    max_allowed_packet = 10M
Index: docs/ref/contrib/gis/db-api.txt
===================================================================
--- docs/ref/contrib/gis/db-api.txt	(revision 0)
+++ docs/ref/contrib/gis/db-api.txt	(revision 0)
@@ -0,0 +1,1330 @@
+======================
+GeoDjango Database API
+======================
+
+GeoDjango's lookup types may be used with any manager method like
+``filter()``, ``exclude()``, etc.  However, the lookup types unique to
+GeoDjango are only available with geographic fields.
+Filters on 'normal' fields (e.g. ``CharField``) may be chained with those on 
+geographic fields.  Thus, geographic queries take the following form (assuming 
+the ``Zipcode`` model used in the `GeoDjango Model API`_)::
+
+    >>> qs = Zipcode.objects.filter(<field>__<lookup_type>=<parameter>)
+    >>> qs = Zipcode.objects.exclude(...)
+
+For example::
+
+    >>> qs = Zipcode.objects.filter(poly__contains=pnt)
+
+In this case, ``poly`` is the geographic field, ``contains`` is the lookup type, 
+and ``pnt`` is the parameter (which may be a ``GEOSGeometry`` object or a string
+of GeoJSON , WKT, or HEXEWKB).
+
+.. note::
+
+    GeoDjango constructs spatial SQL with the ``GeoQuerySet``, a 
+    subclass of Django's ``QuerySet``.  The ``GeoManager`` instance
+    attached to your model allows it to use ``GeoQuerySet``.
+
+.. _GeoDjango Model API: model-api.html
+
+Creating and Saving Geographic Models
+=====================================
+Here is an example of how to create a geometry object (assuming the ``Zipcode``
+model)::
+
+    >>> from zipcode.models import Zipcode
+    >>> z = Zipcode(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
+    >>> z.save()
+
+`GEOS geometry objects`_ may also be used to save geometric models::
+
+    >>> from django.contrib.gis.geos import GEOSGeometry
+    >>> z = Zipcode(code=77096, poly=GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))'))
+    >>> z.save()
+
+Moreover, if the ``GEOSGeometry`` is in a different coordinate system (has a
+different SRID value) than that of the field, then it will be implicitly 
+transformed into the SRID of the model's field, using the spatial database's 
+transform procedure::
+
+    >>> poly_3084 = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))', srid=3084)  # SRID 3084 is 'NAD83(HARN) / Texas Centric Lambert Conformal'
+    >>> z = Zipcode(code=78212, poly=poly_3084)
+    >>> z.save()
+    >>> from django.db import connection
+    >>> print connection.queries[-1]['sql'] # printing the last SQL statement executed (requires DEBUG=True)
+    INSERT INTO "geoapp_zipcode" ("code", "poly") VALUES (78212, ST_Transform(ST_GeomFromWKB('\\001 ... ', 3084), 4326))
+
+Thus, geometry parameters may be passed in using the ``GEOSGeometry`` object, WKT
+(Well Known Text [#]_), HEXEWKB (PostGIS specific -- a WKB geometry in
+hexadecimal [#]_), and GeoJSON [#]_ (requires GDAL).  Essentially, if the input is not a 
+``GEOSGeometry`` object, the geometry field will attempt to create a ``GEOSGeometry``
+instance from the input.
+
+Below are some examples of GEOS Geometry objects, WKT, and HEXEWKB, and
+GeoJSON:
+
+* GEOS Geometry::
+
+    >>> from django.contrib.gis.geos import *
+    >>> pnt  = Point(5, 23)
+    >>> ls   = LineString((0, 0), (5, 23))
+    >>> poly = GEOSGeometry('POLYGON (( 10 10, 10 20, 20 20, 20 15, 10 10))')
+
+* WKT Polygon: ``'POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))'``
+* HEXEWKB Polygon : ``'0103000000010000000 ... 00000000000002440'``
+* GeoJSON Point: ``{ "type": "Point", "coordinates": [100.0, 0.0] }``
+
+.. _GEOS geometry objects: geos.html
+
+Spatial Lookup Types
+====================
+
+PostGIS
+-------
+
+Spatial Operators
+^^^^^^^^^^^^^^^^^
+
+The following lookup types correspond to PostGIS spatial operators. [#]_
+
+``bbcontains``
+~~~~~~~~~~~~~~
+Tests if the geometry field's bounding box completely contains the lookup 
+geometry's bounding box.
+
+Example::
+
+    Zipcode.objects.filter(poly__bbcontains=geom)
+
+PostGIS equivalent::
+  
+    SELECT ... WHERE poly ~ geom
+
+``bboverlaps``
+~~~~~~~~~~~~~~
+Tests if the geometry field's bounding box overlaps the lookup geometry's 
+bounding box.
+
+Example::
+
+    Zipcode.objects.filter(poly__bboverlaps=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE poly && geom
+
+``contained``
+~~~~~~~~~~~~~
+Tests if the geometry field's bounding box is completely contained by the 
+lookup geometry's bounding box.
+
+Example::
+
+    Zipcode.objects.filter(poly__contained=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE poly @ geom
+
+``exact`` or ``same_as``
+~~~~~~~~~~~~~~~~~~~~~~~~
+Tests actual geometric equality of the geometry field against the the given
+lookup geometry, vertex-by-vertex.
+
+The following examples are equivalent::
+
+    Zipcode.objects.filter(poly__exact=geom)
+    Zipcode.objects.filter(poly=geom)
+    Zipcode.objects.filter(poly__same_as=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE poly ~= geom
+
+``left``
+~~~~~~~~
+Tests if the geometry field's bounding box is strictly to the left of the
+lookup geometry's bounding box.
+
+Example::
+
+    Zipcode.objects.filter(poly__left=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE poly << geom
+
+``right``
+~~~~~~~~~
+Tests if the geometry field's bounding box is strictly to the right of the
+lookup geometry's bounding box.
+
+Example::
+
+    Zipcode.objects.filter(poly__right=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE poly >> geom
+
+``overlaps_left``
+~~~~~~~~~~~~~~~~~
+Tests if the geometry field's bounding box overlaps or is to the left of the lookup 
+geometry's bounding box.
+
+Example::
+
+    Zipcode.objects.filter(poly__overlaps_left=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE poly &< geom
+
+``overlaps_right`` 
+~~~~~~~~~~~~~~~~~~
+Tests if the geometry field's bounding box overlaps or is to the right of the lookup 
+geometry's bounding box.
+
+Example::
+
+    Zipcode.objects.filter(poly__overlaps_right=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE poly &> geom
+
+``overlaps_above``
+~~~~~~~~~~~~~~~~~~
+Tests if the geometry field's bounding box overlaps or is above the lookup 
+geometry's bounding box.
+
+Example::
+
+    Zipcode.objects.filter(poly__overlaps_above=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE poly |&> geom
+
+``overlaps_below``
+~~~~~~~~~~~~~~~~~~
+Tests if the geometry field's bounding box overlaps or is below the lookup 
+geometry's bounding box.
+
+Example::
+
+    Zipcode.objects.filter(poly__overlaps_below=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE poly &<| geom
+
+``strictly_above``
+~~~~~~~~~~~~~~~~~~
+Tests if the geometry field's bounding box is strictly above the lookup 
+geometry's bounding box.
+
+Example::
+
+    Zipcode.objects.filter(poly__strictly_above=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE poly |>> geom
+
+``strictly_below``
+~~~~~~~~~~~~~~~~~~
+Tests if the geometry field's bounding box is strictly below the lookup 
+geometry's bounding box.
+
+Example::
+
+    Zipcode.objects.filter(poly__strictly_below=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE poly <<| geom
+
+Geometry Relationship Functions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The following lookup types correspond to PostGIS geometry relationship 
+functions. [#]_  Please note that when using PostGIS 1.3.1 and above, index
+support is automatically "inlined" -- in other words, the bounding box 
+equivalent is automatically evaluated prior to calling these, more 
+computationally expensive, functions.
+
+``contains``
+~~~~~~~~~~~~
+Tests if the geometry field spatially contains the lookup geometry.
+
+Example::
+
+    Zipcode.objects.filter(poly__contains=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE ST_Contains(poly, geom)
+
+``coveredby``
+~~~~~~~~~~~~~
+Tests if no point in the geometry field is outside the lookup geometry. [#]_
+Only available in PostGIS 1.3.1 and above.
+
+Example::
+
+    Zipcode.objects.filter(poly__coveredby=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE ST_CoveredBy(poly, geom)
+
+``covers``
+~~~~~~~~~~
+Tests if no point in the lookup geometry is outside the geometry field. [#]_
+Only available in PostGIS 1.3.1 and above.
+
+Example::
+
+    Zipcode.objects.filter(poly__covers=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE ST_Covers(poly, geom)
+
+``crosses``
+~~~~~~~~~~~
+Tests if the geometry field spatially crosses the lookup geometry.
+
+Example::
+
+    Zipcode.objects.filter(poly__crosses=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE ST_Crosses(poly, geom)
+
+``disjoint``
+~~~~~~~~~~~~
+Tests if the geometry field is spatially disjoint from the lookup geometry.
+
+Example::
+
+    Zipcode.objects.filter(poly__disjoint=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE ST_Disjoint(poly, geom)
+
+.. _dwithin_postgis:
+
+``dwithin``
+~~~~~~~~~~~
+Tests if the geometry field is within the specified distance of the lookup
+geometry; uses indexes if available.  The lookup parameter is a two-element
+tuple: ``(geom, distance)``, where ``distance`` is a ``Distance`` object or a
+numeric value in units.   Only available in PostGIS versions 1.3.1 and above.
+
+.. admonition:: Distance Parameters and Geographic Coordinate Systems
+
+    The ``dwithin`` lookup is meant for projected coordinate systems
+    because PostGIS uses ``ST_Distance``, which calculates the 
+    Cartesian distance between geometries.  In other words,
+    this will not return accurate results for geographic coordinate
+    systems such as WGS84.  Thus, an exception will be raised if a
+    ``Distance`` object is used on a geometry field in a geographic
+    coordinate system.
+    
+    However, a numeric value is allowed for geometry fields in geographic
+    coordinate systems.  This advanced usage allows users to limit
+    querysets by distance more efficiently using units of degrees.
+
+Example::
+
+    # If Zipcode uses a projected coordinate system, this is allowed.
+    Zipcode.objects.filter(poly__dwithin=(geom, D(mi=5)))
+
+    # If Zipcode uses a geographic coordinate system, then the
+    # distance unit must be a numeric value in units of degrees.
+    Zipcode.objects.filter(poly__dwithin=(geom, 0.5))
+
+PostGIS equivalent::
+
+    SELECT ... WHERE ST_DWithin(poly, geom, <units value>)
+
+``equals``
+~~~~~~~~~~
+Tests if the geometry field is spatially equal to the lookup geometry.
+
+Example::
+
+    Zipcode.objects.filter(poly__equals=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE ST_Equals(poly, geom)
+
+``intersects``
+~~~~~~~~~~~~~~
+Tests if the geometry field spatially intersects the lookup geometry.
+
+Example::
+
+    Zipcode.objects.filter(poly__intersects=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE ST_Intersects(poly, geom)
+
+``overlaps``
+~~~~~~~~~~~~
+Tests if the geometry field spatially overlaps the lookup geometry.
+
+Example::
+
+    Zipcode.objects.filter(poly__overlaps=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE ST_Overlaps(poly, geom)
+
+``relate``
+~~~~~~~~~~
+Tests if the geometry field is spatially related to the the lookup geometry by
+the values given in the intersection pattern matrix.  The intersection pattern
+matrix is a string comprising nine characters, which  define intersections between 
+the interior, boundary, and exterior of the geometry field and the lookup geometry.  
+The intersection pattern matrix may only use the following characters:
+``1``, ``2``, ``T``, ``F``, or ``*``.  This lookup type allows users to "fine tune"
+a specific geometric relationship consistent with the DE-9IM model. [#]_
+
+Example::
+
+    # A tuple lookup parameter is used to specify the geometry and
+    # the intersection pattern (the pattern here is for 'contains').
+    Zipcode.objects.filter(poly__relate(geom, 'T*T***FF*'))
+
+PostGIS equivalent::
+
+    SELECT ... WHERE ST_Relate(poly, geom, 'T*T***FF*')
+
+``touches``
+~~~~~~~~~~~
+Tests if the geometry field spatially touches the lookup geometry.
+
+Example::
+
+    Zipcode.objects.filter(poly__touches=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE ST_Touches(poly, geom)
+
+``within``
+~~~~~~~~~~
+Tests if the geometry field is spatially within the lookup geometry.
+
+Example::
+
+    Zipcode.objects.filter(poly__within=geom)
+
+PostGIS equivalent::
+
+    SELECT ... WHERE ST_Within(poly, geom)
+
+
+Oracle
+------
+For more information, see Oracle's `Spatial Operators`__ documentation. [#]_
+
+__ http://download.oracle.com/docs/html/B14255_01/sdo_operat.htm
+
+``contains``
+^^^^^^^^^^^^
+Tests if the geometry field spatially contains the lookup geometry.
+
+Example::
+
+    Zipcode.objects.filter(poly__contains=geom)
+
+Oracle equivalent::
+
+    SELECT ... WHERE SDO_CONTAINS(poly, geom)
+
+``covers``
+^^^^^^^^^^
+Tests if no point in the lookup geometry is outside the geometry field.
+
+Oracle equivalent::
+
+    SELECT ... WHERE SDO_COVERS(poly, geom)
+ 
+``coveredby``
+^^^^^^^^^^^^^
+Tests if no point in the geometry field is outside the lookup geometry.
+
+Oracle equivalent::
+
+    SELECT ... WHERE SDO_COVEREDBY(poly, geom)
+  
+``disjoint``
+^^^^^^^^^^^^
+Tests if the geometry field is spatially disjoint from the lookup geometry.
+
+Oracle equivalent::
+
+    SELECT ... WHERE SDO_GEOM.RELATE(poly, 'DISJOINT', geom, 0.05)
+
+``dwithin``
+^^^^^^^^^^^
+Tests if the geometry field is within the specified distance of the lookup
+geometry; uses indexes if available.  The lookup parameter is a two-element
+tuple: ``(geom, distance)``, where ``distance`` is a ``Distance`` object or a
+numeric value in units.
+
+Oracle equivalent::
+
+    SELECT ... WHERE SDO_WITHIN_DISTANCE(poly, geom, 'distance=distance')
+
+``equals``, ``exact``, ``same_as``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Tests if the geometry field is spatially equal to the lookup geometry.
+The following examples are equivalent on Oracle::
+
+    Zipcode.objects.filter(poly=geom)
+    Zipcode.objects.filter(poly__exact=geom)
+    Zipcode.objects.filter(poly__equals=geom)
+    Zipcode.objects.filter(poly__same_as=geom)
+
+Oracle equivalent::
+
+    SELECT ... WHERE SDO_EQUALS(poly, geom)
+
+``intersects``
+^^^^^^^^^^^^^^
+Tests if the geometry field spatially intersects the lookup geometry.
+
+Oracle equivalent::
+
+    SELECT ... WHERE SDO_OVERLAPBDYINTERSECT(poly, geom)
+
+``overlaps``
+^^^^^^^^^^^^
+Tests if the geometry field spatially overlaps the lookup geometry.
+
+Oracle equivalent::
+
+    SELECT ... WHERE SDO_OVERLAPS(poly, geom)
+
+``relate``
+^^^^^^^^^^
+Tests if the geometry field is spatially related to the the lookup geometry by
+the given mask component.  This lookup requires a tuple parameter, 
+``(geom, mask)``, where ``mask`` is at least one of the nine-intersection 
+patterns: ``TOUCH``, ``OVERLAPBDYDISJOINT``, ``OVERLAPBDYINTERSECT``, 
+``EQUAL``, ``INSIDE``, ``COVEREDBY``, ``CONTAINS``, ``COVERS``, ``ANYINTERACT``, 
+and ``ON``.  Multiple masks may be combined with the logical Boolean operator 
+OR, for example, ``'inside+touch'``. [#]_  The mask relation strings are 
+case-insensitive.
+
+Example::
+
+    # A tuple lookup parameter is used to specify the geometry and
+    # the mask component.
+    Zipcode.objects.filter(poly__relate(geom, 'anyinteract'))
+
+Oracle equivalent:: 
+
+    SELECT ... WHERE SDO_RELATE(poly, geom, 'anyinteract')
+
+``touches``
+^^^^^^^^^^^
+Tests if the geometry field spatially touches the lookup geometry.
+
+Oracle equivalent::
+
+    SELECT ... WHERE SDO_TOUCH(poly, geom)
+
+``within``
+^^^^^^^^^^
+Tests if the geometry field is spatially within (inside) the lookup
+geometry.
+
+Oracle equivalent::
+
+    SELECT ... WHERE SDO_INSIDE(poly, geom)
+
+MySQL
+-----
+For more information, see `Relations on Geometry Minimal Bounding Rectangles (MBRs)`__. [#]_
+
+__ http://dev.mysql.com/doc/refman/5.0/en/relations-on-geometry-mbr.html
+
+``bbcontains``, ``contains``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+* MySQL equivalent ``MBRContains(g1, g2)``
+
+``contained``, ``within``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+* MySQL equivalent ``MBRWithin(g1, g2)``
+
+``disjoint``
+^^^^^^^^^^^^
+* MySQL equivalent ``MBRDisjoint(g1, g2)``
+ 
+``equals``, ``exact``, ``same_as``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+* MySQL equivalent ``MBREqual(g1, g2)``
+
+``intersects``
+^^^^^^^^^^^^^^
+* MySQL equivalent ``MBRIntersects(g1, g2)``
+
+``overlaps``
+^^^^^^^^^^^^
+* MySQL equivalent ``MBROverlaps(g1, g2)``
+
+``touches``
+^^^^^^^^^^^
+* MySQL equivalent ``MBRTouches(g1, g2)`` 
+
+SpatiaLite
+----------
+
+For more information consult the `SpatiaLite SQL functions reference list`__.
+
+__ http://www.gaia-gis.it/spatialite/spatialite-sql-2.3.1.html
+
+``bbcontains``
+^^^^^^^^^^^^^^
+* SpatiaLite equivalient ``MbrContains(g1, g2)``
+
+``bboverlaps``
+^^^^^^^^^^^^^^
+* SpatiaLite equivalent ``MbrOverlaps(g1, g2)``
+
+``contained``
+^^^^^^^^^^^^^
+* SpatiaLite equivalent ``MbrWithin(g1, g2)``
+
+``contains``
+^^^^^^^^^^^^
+* SpatiaLite equivalent ``Contains(g1, g2)``
+
+``crosses``
+^^^^^^^^^^^
+* SpatiaLite equivalent ``Crosses(g1, g2)``
+
+``disjoint``
+^^^^^^^^^^^^
+* SpatiaLite equivalent ``Disjoint(g1, g2)``
+
+``equals``, ``exact``, ``same_as``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+* SpatiaLite equivalent ``Equals(g1, g2)``
+
+``intersects``
+^^^^^^^^^^^^^^
+* SpatiaLite equivalent ``Intersects(g1, g2)``
+
+``overlaps``
+^^^^^^^^^^^^
+* SpatiaLite equivalent ``Overlaps(g1, g2)``
+
+``relate``
+^^^^^^^^^^
+* SpatiaLite equivalent ``Relate(geom, pattern)``
+
+``touches``
+^^^^^^^^^^^
+* SpatiaLite equivalent ``Touches(g1, g2)``
+
+``within``
+^^^^^^^^^^
+* SpatiaLite equivalent ``Within(g1, g2)``
+
+
+Distance Queries
+================
+
+Introduction
+------------
+Distance calculations with spatial data is tricky because, unfortunately,
+the Earth is not flat.  Some distance queries with fields in a geographic
+coordinate system may have to be expressed differently because of 
+limitations in PostGIS.  Please see the `Selecting an SRID`_ section in the 
+model API documentation for more details.
+
+.. _Selecting an SRID: model-api.html#selecting-an-srid
+
+Distance Lookups
+----------------
+*Availability*: PostGIS, Oracle, SpatiaLite
+
+Distance lookups take a tuple parameter comprising:
+
+#. A geometry to base calculations from; and 
+#. A number or ``Distance`` object containing the distance.
+
+If a ``Distance`` [#]_ object is used, it may be expressed in
+any units (the SQL generated will use units converted to those of the field); 
+otherwise, numeric parameters will be assumed to be in the units of the field.
+
+.. note::
+
+    For PostGIS users, the routine ``ST_distance_sphere`` 
+    is used by default for calculating distances on geographic coordinate systems 
+    -- which may only be called with point geometries [#]_.  Thus, 
+    geographic distance lookups on PostGIS are only allowed on ``PointField`` 
+    model fields using points for the geographic parameter.
+
+The following distance lookups are available:
+
+* ``distance_lt``
+* ``distance_lte``
+* ``distance_gt``
+* ``distance_gte``
+* ``dwithin``
+
+In addition, there's the :ref:`distance` ``GeoQuerySet`` method.
+
+For example, let's say we have a ``SouthTexasCity`` model (from the 
+`GeoDjango distance tests`__ ) on a *projected* coordinate system valid for cities 
+in southern Texas::
+
+    from django.contrib.gis.db import models
+    
+    class SouthTexasCity(models.Model):
+        name = models.CharField(max_length=30)
+        # A projected coordinate system (only valid for South Texas!) 
+        # is used, units are in meters.
+        point = models.PointField(srid=32140) 
+        objects = models.GeoManager()
+
+Then distance queries may be performed as follows::
+
+    >>> from django.contrib.gis.geos import *
+    >>> from django.contrib.gis.measure import D # ``D`` is a shortcut for ``Distance``
+    >>> from geoapp import SouthTexasCity 
+    # Distances will be calculated from this point, which does not have to be projected.
+    >>> pnt = fromstr('POINT(-96.876369 29.905320)', srid=4326)
+    # If numeric parameter, units of field (meters in this case) are assumed.
+    >>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, 7000))
+    # Find all Cities within 7 km, > 20 miles away, and > 100 chains  away (an obscure unit)
+    >>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, D(km=7)))
+    >>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(mi=20)))
+    >>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(chain=100)))
+
+__ http://code.djangoproject.com/browser/django/trunk/django/contrib/gis/tests/distapp/models.py
+
+.. _geoqs_methods:
+
+``GeoQuerySet`` Methods
+=======================
+
+``GeoQuerySet`` methods perform a spatial operation on each geographic
+field in the queryset and store its output in a new attribute on the model
+(which is generally the name of the ``GeoQuerySet`` method).
+
+There are also aggregate ``GeoQuerySet`` methods which return a single value
+instead of a queryset.  This section will describe the API and availability
+of every ``GeoQuerySet`` method available in GeoDjango.
+
+With a few exceptions, the following keyword arguments may be used with all
+``GeoQuerySet`` methods:
+
+=====================  =====================================================
+Keyword Argument       Description
+=====================  =====================================================
+``field_name``         By default, ``GeoQuerySet`` methods use the first
+                       geographic field encountered in the model.  This
+                       keyword should be used to specify another 
+                       geographic field (e.g., ``field_name='point2'``)
+                       when there are multiple geographic fields in a model.
+
+                       On PostGIS, the ``field_name`` keyword may also be
+                       used on geometry fields in models that are related
+                       via a ``ForeignKey`` relation (e.g.,
+                       ``field_name='related__point'``).
+    
+``model_att``          By default, ``GeoQuerySet`` methods typically attach
+                       their output in an attribute with the same name as
+                       the ``GeoQuerySet`` method.  Setting this keyword
+                       with the desired attribute name will override this
+                       default behavior.  For example,
+                       ``qs = Zipcode.objects.centroid(model_att='c')`` will
+                       attach the centroid of the ``Zipcode`` geometry field
+                       in a ``c`` attribute on every model rather than in a
+                       ``centroid`` attribute.  
+
+                       This keyword is required if 
+                       a method name clashes with an existing 
+                       ``GeoQuerySet`` method -- if you wanted to use the 
+                       ``area()`` method on model with a ``PolygonField`` 
+		       named ``area``, for example.
+=====================  =====================================================
+
+Aggregate Objects
+-----------------
+.. versionadded:: 1.1
+
+Example::
+
+    >>> from django.contrib.gis.db.models import Extent, Union
+    >>> WorldBorders.objects.aggregate(Extent('mpoly'), Union('mpoly'))
+
+``Collect``
+^^^^^^^^^^^
+
+Returns the same as the :ref:`collect` aggregate method.
+
+``Extent``
+^^^^^^^^^^
+
+Returns the same as the :ref:`extent` aggregate method.
+
+``Extent3D``
+^^^^^^^^^^^^
+.. versionadded:: 1.2
+
+Returns the same as the :ref:`extent3d` aggregate method.
+
+``MakeLine``
+^^^^^^^^^^^^
+
+Returns the same as the :ref:`makeline` aggregate method.
+
+``Union``
+^^^^^^^^^
+
+Returns the same as the :ref:`unionagg` aggregate method.
+
+Aggregate Methods
+-----------------
+
+.. _collect:
+
+``collect()``
+^^^^^^^^^^^^^
+.. versionadded:: 1.1
+
+*Availability*: PostGIS
+
+.. function:: collect()
+
+Returns a ``GEOMETRYCOLLECTION`` or a ``MULTI`` geometry object from the geometry
+column.  This is analagous to a simplified version of the :ref:`unionagg` routine,
+except it can be several orders of magnitude faster than peforming a union because
+it simply rolls up geometries into a collection or multi object, not caring about
+dissolving boundaries.
+
+.. _extent:
+
+``extent()``
+^^^^^^^^^^^^
+*Availability*: PostGIS, Oracle
+
+.. function:: extent()
+
+Returns the extent of the ``GeoQuerySet`` as a four-tuple, comprising the 
+lower left coordinate and the upper right coordinate.
+
+Example::
+
+    >>> qs = City.objects.filter(name__in=('Houston', 'Dallas'))
+    >>> print qs.extent()
+    (-96.8016128540039, 29.7633724212646, -95.3631439208984, 32.782058715820)
+
+
+.. _extent3d:
+
+``extent3d()``
+^^^^^^^^^^^^^^
+.. versionadded:: 1.2
+
+*Availability*: PostGIS
+
+.. function:: extent3d()
+
+Returns the 3D extent of the ``GeoQuerySet`` as a six-tuple, comprising
+the lower left coordinate and upper right coordinate.
+
+Example::
+
+    >>> qs = City.objects.filter(name__in=('Houston', 'Dallas'))
+    >>> print qs.extent3d()
+    (-96.8016128540039, 29.7633724212646, 0, -95.3631439208984, 32.782058715820, 0)
+
+.. _makeline:
+
+``make_line()``
+^^^^^^^^^^^^^^^
+*Availability*: PostGIS
+
+.. function:: make_line()
+
+Returns a ``LineString`` constructed from the point field geometries in the 
+``GeoQuerySet``.  Currently, ordering the queryset has no effect.
+
+Example::
+
+     >>> print City.objects.filter(name__in=('Houston', 'Dallas')).make_line()
+     LINESTRING (-95.3631510000000020 29.7633739999999989, -96.8016109999999941 32.7820570000000018)
+
+.. _unionagg:
+
+``unionagg()``
+^^^^^^^^^^^^^^
+*Availability*: PostGIS, Oracle, SpatiaLite
+
+.. function:: unionagg()
+
+This method returns a ``GEOSGeometry`` object comprising the union of every 
+geometry in the queryset.  Please note that use of `unionagg` is processor intensive 
+and may take a significant amount of time on large querysets.
+
+Example::
+    
+    >>> u = Zipcode.objects.unionagg() # This may take a long time.
+    >>> u = Zipcode.objects.filter(poly__within=bbox).unionagg() # A more sensible approach.
+
+=====================  =====================================================
+Keyword Argument       Description
+=====================  =====================================================
+``tolerance``          This keyword is for Oracle only.  It is for the 
+                       tolerance value used by the ``SDOAGGRTYPE``
+                       procedure; the  `Oracle documentation`__ has more 
+                       details.
+=====================  =====================================================
+
+__ http://download.oracle.com/docs/html/B14255_01/sdo_intro.htm#sthref150 
+
+Measurement
+-----------
+*Availability*: PostGIS, Oracle, SpatiaLite
+
+.. _area
+
+``area()``
+^^^^^^^^^^
+
+.. function:: area()
+Returns the area of the geographic field in an ``area`` attribute on
+each element of this GeoQuerySet.
+
+.. _distance:
+
+``distance(geom)``
+^^^^^^^^^^^^^^^^^^
+
+.. function:: distance(geom)
+
+This method takes a geometry as a parameter, and attaches a ``distance`` 
+attribute to every model in the returned queryset that contains the 
+distance (as a ``Distance`` object) to the given geometry.
+
+In the following example (taken from the `GeoDjango distance tests`__), 
+the distance from the `Tasmanian`__ city of Hobart to every other 
+``PointField`` in the ``AustraliaCity`` queryset is calculated::
+
+    >>> pnt = AustraliaCity.objects.get(name='Hobart').point
+    >>> for city in AustraliaCity.objects.distance(pnt): print city.name, city.distance
+    Wollongong 990071.220408 m
+    Shellharbour 972804.613941 m
+    Thirroul 1002334.36351 m
+    Mittagong 975691.632637 m
+    Batemans Bay 834342.185561 m
+    Canberra 598140.268959 m
+    Melbourne 575337.765042 m
+    Sydney 1056978.87363 m
+    Hobart 0.0 m
+    Adelaide 1162031.83522 m
+    Hillsdale 1049200.46122 m
+
+.. note::
+
+    Because the ``distance`` attribute is a ``Distance`` object, you can
+    easily express the value in the units of your choice.  For example,
+    ``city.distance.mi`` is the distance value in miles and
+    ``city.distance.km`` is the distance value in kilometers.  See the
+    `distance documentation`_ for usage details and the list of
+    `supported units`_.
+
+.. _distance documentation: measure.html#the-distance-and-area-objects
+.. _supported units: measure.html#supported-units
+
+__ http://en.wikipedia.org/wiki/Tasmania
+__ http://code.djangoproject.com/browser/django/trunk/django/contrib/gis/tests/distapp/models.py
+
+``length()``
+^^^^^^^^^^^^
+.. function:: length()
+Returns the length of the geometry field in a ``length`` attribute
+(a ``Distance`` object) on each model in the queryset.
+
+``perimeter()``
+^^^^^^^^^^^^^^^
+.. function:: perimiter()
+Returns the perimeter of the geometry field in a ``perimeter`` attribute
+(a ``Distance`` object) on each model in the queryset.
+
+Geometry Methods
+----------------
+
+With the exception of ``transform``, all of the following attach geometry objects 
+to each element of the ``GeoQuerySet`` that is the result of the method.
+
+``centroid()``
+^^^^^^^^^^^^^^
+*Availability*: PostGIS, Oracle, SpatiaLite
+
+.. function:: centroid()
+Returns the ``centroid`` value for the geographic field in a ``centroid``
+attribute on each element of the ``GeoQuerySet``.
+
+``envelope()``
+^^^^^^^^^^^^^^
+*Availability*: PostGIS, SpatiaLite
+
+.. function:: envelope()
+Returns a geometry representing the bounding box of the geometry field in
+an ``envelope`` attribute on each element of the ``GeoQuerySet``.
+
+``point_on_surface()``
+^^^^^^^^^^^^^^^^^^^^^^
+*Availability*: PostGIS, Oracle, SpatiaLite
+
+.. function: point_on_surface()
+Returns a Point geometry guaranteed to lie on the surface of the
+Geometry field in a `point_on_surface` attribute on each element
+of this GeoQuerySet; otherwise sets with None.
+
+``scale(x, y, z=0.0)``
+^^^^^^^^^^^^^^^^^^^^^^
+*Availability*: PostGIS, SpatiaLite
+
+.. function:: scale(x, y, z=0.0)
+``snap_to_grid(*args)``
+^^^^^^^^^^^^^^^^^^^^^^^
+.. versionadded:: 1.1
+
+.. function:: snap_to_grid(*args)
+Snap all points of the input geometry to the grid.  How the
+geometry is snapped to the grid depends on how many numeric
+(either float, integer, or long) arguments are given.
+
+===================  =====================================================
+Number of Arguments  Description
+===================  =====================================================
+1                    A single size to snap bot the X and Y grids to.
+2                    X and Y sizes to snap the grid to.
+4                    X, Y sizes and the corresponding X, Y origins.
+===================  =====================================================
+
+``translate(x, y, z=0.0)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+*Availability*: PostGIS, SpatiaLite
+
+.. function:: translate(x, y, z=0.0)
+Translates the geometry to a new location using the given numeric
+parameters as offsets.
+
+``transform(srid)``
+^^^^^^^^^^^^^^^^^^^
+*Availability*: PostGIS, Oracle
+
+.. function:: transform(srid)
+The ``transform`` method transforms the geometries in a model to the spatial
+reference system specified by the ``srid`` parameter.  If no ``srid`` is given,
+then 4326 (WGS84) is used by default.
+
+.. note ::
+    
+    What spatial reference system an integer SRID corresponds to may depend on 
+    the spatial database used.  In other words, the SRID numbers used for Oracle 
+    are not necessarily the same as those used by PostGIS.
+
+Example::
+
+    >>> qs = Zipcode.objects.all().transform() # Transforms to WGS84
+    >>> qs = Zipcode.objects.all().transform(32140) # Transforming to "NAD83 / Texas South Central"
+    >>> print qs[0].poly.srid
+    32140
+    >>> print qs[0].poly
+    POLYGON ((234055.1698884720099159 4937796.9232223574072123 ...
+
+Geometry Operations
+-------------------
+*Availability*: PostGIS, Oracle, SpatiaLite
+
+The following methods all take a geometry as a parameter and attach a geometry
+to each element of the ``GeoQuerySet`` that is the result of the operation.
+
+``difference(geom)``
+^^^^^^^^^^^^^^^^^^^^
+
+.. function:: difference(geom)
+Returns the spatial difference of the geographic field with the given
+geometry in a ``difference`` attribute on each element of the 
+``GeoQuerySet``.
+
+``intersection(geom)``
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. function:: intersection(geom)
+Returns the spatial intersection of the geographic field with the
+given geometry in an ``intersection`` attribute on each element of the 
+``GeoQuerySet``.
+
+``sym_difference(geom)``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. function:: sym_difference(geom)
+Returns the symmetric difference of the geographic field with the
+given geometry in a ``sym_difference`` attribute on each element of the
+``GeoQuerySet``.
+
+``union(geom)``
+^^^^^^^^^^^^^^^
+
+.. function:: union(geom)
+Returns the union of the geographic field with the given
+geometry in an ``union`` attribute on each element of the
+``GeoQuerySet``.
+
+Output
+------
+
+The following ``GeoQuerySet`` methods will return an attribute that has the value 
+of the geometry field in each model converted to the requested output format.
+
+``geojson()``
+^^^^^^^^^^^^^
+.. versionadded:: 1.1
+
+*Availability*: PostGIS
+
+.. function:: geojson()
+Attaches a ``geojson`` attribute to every model in the queryset that contains the
+`GeoJSON`__ representation of the geometry.
+
+=====================  =====================================================
+Keyword Argument       Description
+=====================  =====================================================
+``precision``          It may be used to specify the number of significant 
+                       digits for the coordinates in the GeoJSON 
+                       representation -- the default value is 8.
+
+``crs``                Set this to ``True`` if you want the coordinate
+                       reference system to be included in the returned
+                       GeoJSON.
+
+``bbox``               Set this to ``True`` if you want the bounding box
+                       to be included in the returned GeoJSON.
+=====================  =====================================================
+
+__ http://geojson.org/
+
+``gml()``
+^^^^^^^^^
+*Availability*: PostGIS, Oracle
+
+.. function:: gml()
+Attaches a ``gml`` attribute to every model in the queryset that contains the 
+`Geographic Markup Language (GML)`__ representation of the geometry. 
+
+Example::
+
+    >>> qs = Zipcode.objects.all().gml()
+    >>> print qs[0].gml
+    <gml:Polygon srsName="EPSG:4326"><gml:OuterBoundaryIs>-147.78711,70.245363 ...  -147.78711,70.245363</gml:OuterBoundaryIs></gml:Polygon>
+
+=====================  =====================================================
+Keyword Argument       Description
+=====================  =====================================================
+``precision``          This keyword is for PostGIS only.  It may be used 
+                       to specify the number of significant digits for the 
+                       coordinates in the GML representation -- the default 
+                       value is 8.
+
+``version``            This keyword is for PostGIS only.  It may be used to
+                       specify the GML version used, and may only be values
+                       of 2 or 3.  The default value is 2.
+=====================  =====================================================
+
+__ http://en.wikipedia.org/wiki/Geography_Markup_Language
+
+``kml()``
+^^^^^^^^^
+*Availability*: PostGIS
+
+.. function:: kml()
+Attaches a ``kml`` attribute to every model in the queryset that contains the 
+`Keyhole Markup Language (KML)`__ representation of the geometry fields. It 
+should be noted that the contents of the KML are transformed to WGS84 if 
+necessary.
+
+Example::
+
+    >>> qs = Zipcode.objects.all().kml()
+    >>> print qs[0].kml
+    <Polygon><outerBoundaryIs><LinearRing><coordinates>-103.04135,36.217596,0 ... -103.04135,36.217596,0</coordinates></LinearRing></outerBoundaryIs></Polygon>
+
+=====================  =====================================================
+Keyword Argument       Description
+=====================  =====================================================
+``precision``          This keyword may be used to specify the number of 
+                       significant digits for the coordinates in the KML 
+                       representation -- the default value is 8.
+=====================  =====================================================
+
+__ http://code.google.com/apis/kml/documentation/
+
+``svg()``
+^^^^^^^^^
+*Availability*: PostGIS, SpatiaLite
+
+.. function:: svg()
+Attaches a ``svg`` attribute to every model in the queryset that contains
+the `Scalable Vector Graphics (SVG)`__ path data of the geometry fields.
+
+=====================  =====================================================
+Keyword Argument       Description
+=====================  =====================================================
+``relative``           If set to ``True``, the path data will be implemented
+                       in terms of relative moves.  Defaults to ``False``, 
+		       meaning that absolute moves are used instead.
+
+``precision``          This keyword may be used to specify the number of 
+                       significant digits for the coordinates in the SVG 
+                       representation -- the default value is 8.
+=====================  =====================================================
+
+__ http://www.w3.org/Graphics/SVG/
+
+Miscellaneous
+-------------
+
+``mem_size()``
+^^^^^^^^^^^^^^
+*Availability*: PostGIS
+
+.. function:: mem_size()
+Returns the memory size (number of bytes) that the geometry field takes
+in a ``mem_size`` attribute  on each element of the ``GeoQuerySet``.
+
+``num_geom()``
+^^^^^^^^^^^^^^
+*Availability*: PostGIS, Oracle, SpatiaLite
+
+.. function:: num_geom()
+Returns the number of geometries in a ``num_geom`` attribute on
+each element of the ``GeoQuerySet`` if the geometry field is a
+collection (e.g., a ``GEOMETRYCOLLECTION`` or ``MULTI*`` field);
+otherwise sets with ``None``.
+
+``num_points()``
+^^^^^^^^^^^^^^^^
+*Availability*: PostGIS, Oracle, SpatiaLite
+
+.. function:: num_points()
+Returns the number of points in the first linestring in the
+geometry field in a ``num_points`` attribute on each element of
+the ``GeoQuerySet``; otherwise sets with ``None``.
+
+Compatibility Table
+===================
+
+Spatial Lookup Types
+--------------------
+The following table provides a summary of what lookup types are available
+on each spatial backend.
+
+===========================  =========  ========  ============ ==========
+Lookup Type                  PostGIS    Oracle    MySQL [#]_   SpatiaLite
+===========================  =========  ========  ============ ==========
+``bbcontains``               X                    X            X
+``bboverlaps``               X                    X            X
+``contained``                X                    X            X
+``contains``                 X          X         X            X
+``coveredby``                X          X
+``covers``                   X          X
+``crosses``                  X                                 X
+``disjoint``                 X          X         X            X
+``distance_gt``              X          X                      X
+``distance_gte``             X          X                      X
+``distance_lt``              X          X                      X
+``distance_lte``             X          X                      X
+``dwithin``                  X          X
+``equals``                   X          X         X            X
+``exact``                    X          X         X            X
+``intersects``               X          X         X            X
+``overlaps``                 X          X         X            X
+``relate``                   X          X                      X
+``same_as``                  X          X         X            X
+``touches``                  X          X         X            X
+``within``                   X          X         X            X
+``left``                     X
+``right``                    X
+``overlaps_left``            X
+``overlaps_right``           X
+``overlaps_above``           X
+``overlaps_below``           X
+``strictly_above``           X
+``strictly_below``           X
+===========================  =========  ========  ============ ==========
+
+``GeoQuerySet`` Methods
+-----------------------
+The following table provides a summary of what ``GeoQuerySet`` methods
+are available on each spatial backend.  Please note that MySQL does not 
+support any of these methods, and is thus excluded from the table.
+
+===========================  =========  ======== ==========
+Method                       PostGIS    Oracle   SpatiaLite
+===========================  =========  ======== ==========
+``area``                     X          X        X
+``centroid``                 X          X        X
+``collect``                  X            
+``difference``               X          X        X
+``distance``                 X          X        X
+``envelope``                 X                   X
+``extent``                   X          X
+``extent3d``                 X
+``geojson``                  X
+``gml``                      X          X
+``intersection``             X          X        X
+``kml``                      X
+``length``                   X          X        X
+``make_line``                X
+``mem_size``                 X 
+``num_geom``                 X          X        X
+``num_points``               X          X        X
+``perimeter``                X          X
+``point_on_surface``         X          X        X
+``scale``                    X                   X
+``snap_to_grid``             X
+``svg``                      X                   X
+``sym_difference``           X          X        X
+``transform``                X          X        X
+``translate``                X                   X
+``union``                    X          X        X
+``unionagg``                 X          X        X
+===========================  =========  ======== ==========    
+
+.. rubric:: Footnotes
+.. [#] *See* Open Geospatial Consortium, Inc., `OpenGIS Simple Feature Specification For SQL <http://www.opengis.org/docs/99-049.pdf>`_, Document 99-049 (May 5, 1999), at  Ch. 3.2.5, p. 3-11 (SQL Textual Representation of Geometry).
+.. [#] *See* `PostGIS EWKB, EWKT and Canonical Forms <http://postgis.refractions.net/documentation/manual-1.3/ch04.html#id2571020>`_, PostGIS documentation at Ch. 4.1.2.
+.. [#] *See* Howard Butler, Martin Daly, Allan Doyle, Tim Schaub, & Christopher Schmidt, `The GeoJSON Format Specification <http://geojson.org/geojson-spec.html>`_, Revision 1.0 (June 16, 2008).
+.. [#] *See generally*, `Operators <http://postgis.refractions.net/documentation/manual-1.3/ch06.html#id2576880>`_, PostGIS Documentation at Ch. 6.2.2.
+.. [#] *See generally*, `Geometry Relationship Functions <http://postgis.refractions.net/documentation/manual-1.3/ch06.html#id2574517>`_ PostGIS Documentation at Ch. 6.1.2.
+.. [#] For an explanation of this routine, see `this entry <http://lin-ear-th-inking.blogspot.com/2007/06/subtleties-of-ogc-covers-spatial.html>`_ at the blog of Martin Davis (a PostGIS developer).
+.. [#] *See id.*
+.. [#] *See* `OpenGIS Simple Feature Specification For SQL <http://www.opengis.org/docs/99-049.pdf>`_, at Ch. 2.1.13.2, p. 2-13 (The Dimensionally Extended Nine-Intersection Model).
+.. [#] Oracle Spatial User's Guide and Manual, at Ch. 11.
+.. [#] *See id.* at `SDO_RELATE documentation <http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14255/sdo_operat.htm#sthref845>`_.
+.. [#] MySQL 5.0 Reference Manual, at Ch. 17.5.5.
+.. [#] *See* the `distance documentation`_ for more information on the ``Distance`` object. 
+.. [#] *See* ``ST_distance_sphere`` in `Measurement Functions <http://postgis.refractions.net/documentation/manual-1.3/ch06.html#id2577138>`_, PostGIS documentation at Ch. 6.2.3.
+.. [#] MySQL only supports bounding box operations (known as minimum bounding rectangles, or MBR, in MySQL).  Thus, spatial lookups such as ``contains`` are really equivalent to ``bbcontains``.
Index: docs/ref/contrib/gis/geos.txt
===================================================================
--- docs/ref/contrib/gis/geos.txt	(revision 0)
+++ docs/ref/contrib/gis/geos.txt	(revision 0)
@@ -0,0 +1,936 @@
+========
+GEOS API
+========
+
+Background
+==========
+
+What is GEOS?
+-------------
+
+`GEOS`__ stands for **G**\ eometry **E**\ ngine - **O**\ pen **S**\ ource, and is a C++ 
+port of the  `Java Topology Suite`__, implementing the OpenGIS
+`Simple Features for SQL`__ spatial predicate functions and spatial operators. 
+GEOS, now an OSGeo project, was initially developed and maintained by 
+`Refractions Research`__ of Victoria, Canada.
+
+__ http://trac.osgeo.org/geos/
+__ http://sourceforge.net/projects/jts-topo-suite/
+__ http://www.opengeospatial.org/standards/sfs
+__ http://www.refractions.net/
+
+Why the new API?
+----------------
+1. The GEOS SWIG wrapper is no longer maintained, and requires the installation 
+   of `SWIG`__. [#]_
+2. The `PCL implementation`__ is over 2K+ lines of C and would make PCL a 
+   requisite package for the GeoDjango application stack.
+3. Cross-platform compatibility.
+
+Thus, the Python ``ctypes`` [#]_ package was used to wrap the `GEOS C API`__
+to bring the rich capabilities of GEOS to Python and GeoDjango.
+
+Features:
+
+* A BSD-licensed interface to the GEOS geometry routines, implemented purely 
+  in Python using ``ctypes``.
+* Loosely-coupled to GeoDjango.  For example, GEOS geometry objects may be 
+  used outside a django project/application (no need to have 
+  ``DJANGO_SETTINGS_MODULE`` set, etc.)
+* Mutability.  GEOS Geometry objects may be modified.
+* Cross-platform and tested.  GeoDjango GEOS geometries are well-tested and 
+  compatible with Windows, Linux, Solaris, and Mac OS X platforms.
+
+__ http://www.swig.org/
+__ http://trac.gispython.org/projects/PCL/browser/PCL/trunk/PCL-Core/cartography/geometry
+__ http://trac.osgeo.org/geos/browser/trunk/capi/geos_c.h.in
+
+Related Work
+------------
+
+The ``GEOSGeometry`` interface was first committed to the Django SVN by Justin
+Bronn (the lead developer of GeoDjango) in April, 2007. [#]_  After learning of 
+GeoDjango's interface [#]_, Sean Gillies created his own ``ctypes`` interface, 
+"Shapely." [#]_  Justin Bronn declined to merge the projects because Shapely 
+was initially licensed under the LGPL, a license incompatible with GeoDjango. [#]_
+While Shapely was later relicensed under the BSD license (the same as GeoDjango)
+[#]_, differences in design and implementation prevent the projects from 
+merging at the moment, but are not irreconcilable.
+
+Geometry Objects
+================
+
+.. _point:
+
+``Point``
+---------
+
+.. class:: Point
+
+The ``Point`` object may be initialized with either a tuple, or individual
+parameters.  For example::
+
+    >>> from django.contrib.gis.geos import Point
+    >>> p = Point((5, 23)) # 2D point, passed in as a tuple
+    >>> p = Point(5, 23) # Same, passed in with individual parameters
+
+The ``srid`` keyword may be used to specify the SRID for the point::
+
+   >>> pnt = Point(5, 23, srid=4326)
+
+Additionally, 3D geometries may be created by specifing a Z value::
+
+   >>> pnt_3d = Point(5, 23, 17) # Also: Point( (5, 23, 17) )
+   >>> pnt_3d.hasz
+   True
+   >>> pnt_3d.z
+   17
+
+Properties
+^^^^^^^^^^
+
+.. attribute:: x
+
+This property sets or retrieves the X coordinate for the point.
+
+.. attribute:: y
+
+This property sets or retrieves the Y coordinate for the point.
+
+.. attribute:: z
+
+This property sets or retrieves the Z (3D) coordinate for the point.
+If the point has no Z coordinate, ``None`` is returned.
+
+.. note:
+
+     The ``Point`` must have been created as 3D before it is possible
+     to set the ``z`` property.
+
+.. _linestring:
+
+.. class:: LineString
+
+.. class:: LinearRing
+
+``LineString`` objects initialize on a given sequence.  For example, the constructor may 
+take lists, tuples, `NumPy`__ arrays of X,Y[,Z] pairs, or ``Point`` objects.  If ``Point`` 
+objects are used, ownership of the points is *not* transferred to the ``LineString`` 
+object.  Examples::
+
+    >>> from django.contrib.gis.geos import LineString, Point
+    >>> ls = LineString((1, 1), (2, 2))
+    >>> ls = LineString([(1, 1), (2, 2)])
+    >>> ls = LineString(Point(1, 1), Point(2, 2))
+    >>> from numpy import array
+    >>> ls = LineString(array([(1, 1), (2, 2)]))
+
+``LinearRing`` objects are subclasses of ``LineString``; however, an error will
+be raised if the points used during initialization are not closed (the first
+point is equal to the last point)::
+
+    >>> from django.contrib.gis.geos import LinearRing
+    >>> lr = LinearRing((0, 0), (0, 1), (1, 1), (1, 0), (0, 0))
+    >>> lr = LinearRing((0, 0), (0, 1))
+    GEOS_ERROR: IllegalArgumentException: points must form a closed linestring
+
+__ http://numpy.scipy.org/
+
+Methods
+^^^^^^^
+
+.. method:: LineString(coords)
+
+.. attribute:: x
+
+This property returns the X values in a list, or a NumPy array (if installed).
+
+.. attribute:: y
+
+This property returns the Y values in a list, or a NumPy array (if installed).
+
+.. attribute:: z
+
+This property returns the Z values in a list, or a NumPy array (if installed).
+
+.. _polygon:
+
+``Polygon``
+-----------
+
+.. class:: Polygon
+
+Polygons are composed of an exterior ring (the shell), and may also have
+interior rings that denote areas excluded from the exterior.
+
+Methods
+^^^^^^^
+
+``Polygon(rings)``
+~~~~~~~~~~~~~~~~~~
+The ``Polygon`` initializes on arguments that are either ``LinearRing`` instances
+or may be accepted by the ``LinearRing`` constructor.
+
+``from_bbox(bbox)``
+~~~~~~~~~~~~~~~~~~~
+.. versionadded:: 1.1
+.. method:: from_bbox(bbox)
+
+Returns a new ``Polygon`` object for the given bounding box.  The bounding box
+should be a four-tuple comprising the X and Y minimum values followed by the
+X and Y maximum values.  For example::
+
+    >>> from django.contrib.gis.geos import Polygon
+    >>> bbox = (0, 0, 5, 5)
+    >>> poly = Polygon.from_bbox(bbox)
+    >>> print poly
+    POLYGON ((0.0000000000000000 0.0000000000000000, 0.0000000000000000 5.0000000000000000, 5.0000000000000000 5.0000000000000000, 5.0000000000000000 0.0000000000000000, 0.0000000000000000 0.0000000000000000))
+
+``shell``, ``exterior_ring``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. method:: shell()
+.. method:: exterior_ring()
+
+Returns a ``LinearRing`` corresponding to the exterior ring, or shell, of the
+``Polygon``.
+
+``num_interior_rings``
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. method:: num_interior_rings
+
+Returns the number of interior rings contained in the ``Polygon``.
+
+Geometry Collections
+====================
+
+.. _multipoint:
+
+``MultiPoint``
+--------------
+
+.. class:: MultiPoint
+
+    >>> from django.contrib.gis.geos import Point
+    >>> from django.contrib.gis.geos import MultiPoint
+    >>> p1 = Point((0,0))
+    >>> p2 = Point((1,2))
+    >>> mp = MultiPoint(p1, p2)
+    >>> mp
+    <MultiPoint object>
+    >>> mp[0].wkt
+    'POINT (0.0000000000000000 0.0000000000000000)'
+    >>> len(mp)
+    2
+    >>> [ p.wkt for p in mp ]
+    ['POINT (0.0000000000000000 0.0000000000000000)', 'POINT (1.0000000000000000 2.0000000000000000)']
+    >>> mp.ring
+    False
+
+.. _multilinestring:
+
+``MultiLineString``
+-------------------
+
+.. class:: MultiLineString
+
+.. _multipolygon:
+
+``MultiPolygon``
+----------------
+
+.. class:: MultiPolygon
+
+Methods
+^^^^^^^
+
+``cascaded_union``
+~~~~~~~~~~~~~~~~~~
+.. versionadded:: 1.1
+
+.. method:: cascaded_union
+
+.. note::
+
+    Use of this method requires at least GEOS 3.1.
+
+.. _geometrycollection:
+
+``GeometryCollection``
+----------------------
+
+.. class:: GeometryCollection
+
+.. _prepared:
+
+Prepared Geometries
+===================
+.. versionadded: 1.1
+
+In order to obtain a prepared geometry, just access the ``prepared``
+property on any ``GEOSGeometry`` object.  Once you have a
+``PreparedGeometry`` instance its spatial predicate methods, listed below,
+may be used with other ``GEOSGeometry`` objects.  An operation with a prepared
+geometry can be orders of magnitude faster -- the more complex the geometry 
+that is prepared, the larger the speedup in the operation.
+
+.. note::
+
+   GEOS 3.1 is *required* in order to use prepared geometries.
+
+For example::
+
+    >>> from django.contrib.gis.geos import Point, Polygon
+    >>> poly = Polygon.from_bbox((0, 0, 5, 5))
+    >>> prep_poly = poly.prepared
+    >>> prep_poly.contains(Point(2.5, 2.5))
+    True
+
+``PreparedGeometry``
+--------------------
+
+.. class:: PreparedGeometry
+
+All methods on ``PreparedGeometry`` take an ``other`` argument, which 
+must be a ``GEOSGeometry`` object.
+
+``contains(other)``
+^^^^^^^^^^^^^^^^^^^
+
+.. method:: contains(other)
+
+``contains_properly(other)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. method:: contains_properly(other)
+
+``covers(other)``
+^^^^^^^^^^^^^^^^^
+
+.. method:: covers(other)
+
+``intersects(other)``
+^^^^^^^^^^^^^^^^^^^^^
+
+.. method:: intersects(other)
+
+I/O Objects
+===========
+.. versionadded: 1.1
+
+Inside GEOS, I/O classes are used to output geometries to WKT, WKB, and EWKB.
+GeoDjango allows access to these I/O classes if finer-grained control of
+serialization is required.  Typically, 
+
+Reader Objects
+--------------
+
+The reader I/O classes simply return a ``GEOSGeometry`` instance from the
+WKB and/or WKT input given to their ``read(geom)`` method.
+
+``WKBReader``
+^^^^^^^^^^^^^
+
+.. class:: WKBReader
+
+Example::
+
+    >>> from django.contrib.gis.geos import WKBReader
+    >>> wkb_r = WKBReader()
+    >>> wkb_r.read('0101000000000000000000F03F000000000000F03F')
+    <Point object at 0x103a88910>
+
+``WKTReader``
+^^^^^^^^^^^^^
+
+.. class:: WKTReader
+
+Example::
+
+    >>> from django.contrib.gis.geos import WKTReader
+    >>> wkt_r = WKTReader()
+    >>> wkt_r.read('POINT(1 1)')
+    <Point object at 0x103a88b50>
+
+Writer Objects
+--------------
+
+All writer objects have a ``write(geom)`` method that returns either the
+WKB or WKT of the given geometry.  In addition, ``WKBWriter`` objects
+also have properties that may be used to change the byte order, and or
+include the SRID and 3D values (in other words, EWKB).
+
+``WKBWriter``
+^^^^^^^^^^^^^
+
+.. class:: WKBWriter
+
+The ``WKBWriter`` provides the most control over its output.  By default it
+returns OGC-compliant WKB when it's ``write`` method is called.  However, 
+it has properties that
+
+``write(geom)``
+~~~~~~~~~~~~~~~
+
+.. function:: write(geom)
+
+Returns the WKB of the given geometry as a Python ``buffer`` object.
+Example::
+
+    >>> from django.contrib.gis.geos import Point, WKBWriter
+    >>> pnt = Point(1, 1)
+    >>> wkb_w = WKBWriter()
+    >>> wkb_w.write(pnt)
+    <read-only buffer for 0x103a898f0, size -1, offset 0 at 0x103a89930>
+
+``write_hex(geom)``
+~~~~~~~~~~~~~~~~~~~
+
+.. function:: write_hex(geom)
+
+Returns WKB of the geometry in hexadecimal.  Example::
+
+    >>> from django.contrib.gis.geos import Point, WKBWriter
+    >>> pnt = Point(1, 1)
+    >>> wkb_w = WKBWriter()
+    >>> wkb_w.write_hex(pnt)
+    '0101000000000000000000F03F000000000000F03F'
+
+``byteorder``
+~~~~~~~~~~~~~
+
+.. function:: byteorder
+
+This property may be be set to change the byte-order of the geometry
+representation.
+
+=============== =================================================
+Byteorder Value Description
+=============== =================================================
+0               Big Endian (e.g., compatible with RISC systems)
+1               Little Endian (e.g., compatible with x86 systems)
+=============== =================================================
+
+Example::
+
+    >>> from django.contrib.gis.geos import Point, WKBWriter
+    >>> wkb_w = WKBWriter()
+    >>> pnt = Point(1, 1)
+    >>> wkb_w.write_hex(pnt)
+    '0101000000000000000000F03F000000000000F03F'
+    >>> wkb_w.byteorder = 0
+    '00000000013FF00000000000003FF0000000000000'
+
+``outdim``
+~~~~~~~~~~
+
+.. attribute:: outdim
+
+This property may be set to change the output dimension of the geometry
+representation.  In other words, if you have a 3D geometry then set to 3
+so that the Z value is included in the WKB.
+
+============ ===========================
+Outdim Value Description
+============ ===========================
+2            The default, output 2D WKB.
+3            Output 3D EWKB.
+============ ===========================
+
+Example::
+
+    >>> from django.contrib.gis.geos import Point, WKBWriter
+    >>> wkb_w = WKBWriter()
+    >>> wkb_w.outdim
+    2
+    >>> pnt = Point(1, 1, 1)
+    >>> wkb_w.write_hex(pnt) # By default, no Z value included:
+    '0101000000000000000000F03F000000000000F03F'
+    >>> wkb_w.outdim = 3 # Tell writer to include Z values
+    >>> wkb_w.write_hex(pnt)
+    '0101000080000000000000F03F000000000000F03F000000000000F03F'
+
+``srid``
+~~~~~~~~
+
+.. attribute:: srid
+
+Set this property with a boolean to indicate whether the SRID of the
+geometry should be included with the WKB representation.  Example::
+
+    >>> from django.contrib.gis.geos import Point, WKBWriter
+    >>> wkb_w = WKBWriter()
+    >>> pnt = Point(1, 1, srid=4326)
+    >>> wkb_w.write_hex(pnt) # By default, no SRID included:
+    '0101000000000000000000F03F000000000000F03F'
+    >>> wkb_w.srid = True # Tell writer to include SRID
+    >>> wkb_w.write_hex(pnt)
+    '0101000020E6100000000000000000F03F000000000000F03F'
+
+``WKTWriter``
+^^^^^^^^^^^^^
+
+.. class:: WKTWriter
+
+``write(geom)``
+~~~~~~~~~~~~~~~
+
+.. method:: write(geom)
+
+Returns the WKT of the given geometry. Example::
+
+    >>> from django.contrib.gis.geos import Point, WKTWriter
+    >>> pnt = Point(1, 1)
+    >>> wkt_w = WKTWriter()
+    >>> wkt_w.write(pnt)
+    'POINT (1.0000000000000000 1.0000000000000000)'
+
+API
+===
+
+Creation
+--------
+
+``GEOSGeometry(geo_input, srid=None)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. class:: GEOSGeometry
+
+Geometries may be created using the ``GEOSGeometry`` constructor; ``geo_input``
+may be any of the following types of data:
+
+============  ======================  =========================================================================================
+Input Type    Python Type             Example
+============  ======================  =========================================================================================
+WKT           ``str`` / ``unicode``   ``'POINT(5 23)'``
+EWKT          ``str`` / ``unicode``   ``'SRID=4326;POINT(5 23)'``
+HEX           ``str`` / ``unicode``   ``'010100000000000000000014400000000000003740'``
+HEXEWKB       ``str`` / ``unicode``   ``''0101000020E610000000000000000014400000000000003740'``
+GeoJSON       ``str`` / ``unicode``   ``'{ "type": "Point", "coordinates": [ 5.000000, 23.000000 ] }'``
+WKB           ``buffer``              ``buffer('\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x007@')``
+============  ======================  =========================================================================================
+
+While this may seem like an acronym soup, all are standardized geospatial data
+formats or extensions thereof.
+
+The ``srid`` keyword may be used to set the spatial reference system 
+identifier number for the geometry.  This will be used to conduct any needed 
+transformations for spatial lookups and geographic model creation.
+
+``fromfile(file_h)``
+^^^^^^^^^^^^^^^^^^^^
+This factory creates a GEOS geometry from the given file name or an open
+file handle (1.1 only)::
+
+    >>> from django.contrib.gis.geos import fromfile
+    >>> g = fromfile('/home/bob/geom.wkt')
+
+``fromstr(string)``
+^^^^^^^^^^^^^^^^^^^
+GEOS geometry objects may be created from strings using the ``fromstr()`` 
+factory, or using the constructor for each geometry object (as described 
+above)::
+
+    >>> from django.contrib.gis.geos import fromstr
+    >>> pnt = fromstr('POINT(-90.5 29.5)', srid=4326)
+
+It should be noted that ``fromstr`` is a shortcut to the constructor for the 
+base ``GEOSGeometry`` object.
+
+Geometry Properties
+-------------------
+
+``empty``
+^^^^^^^^^
+.. attribute:: empty
+Returns whether or not the set of points in the geometry is empty. 
+
+``geom_type``
+^^^^^^^^^^^^^
+.. attribute:: geom_type
+Returns a string corresponding to the type of geometry.  For example::
+
+    >>> pnt = GEOSGeometry('POINT(5 23)')
+    >>> pnt.geom_type
+    'Point'
+
+``geom_typeid``
+^^^^^^^^^^^^^^^
+.. attribute:: geom_typeid
+Returns the GEOS geometry type identification number.  The following table
+shows the value for each geometry type:
+
+======================  ========
+Geometry                ID
+======================  ========
+``Point``               0
+``LineString``          1
+``LinearRing``          2
+``Polygon``             3
+``MultiPoint``          4
+``MultiLineString``     5
+``MultiPolygon``        6
+``GeometryCollection``  7
+======================  ========
+
+``hasz``
+^^^^^^^^
+.. attribute:: hasz
+Returns a boolean indicating whether the geometry is three-dimensional.  
+
+``num_coords``, ``num_points``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. attribute:: num_coords
+.. attribute:: num_points
+Returns the total number of coordinates in this geometry.  For
+polygons and collections, this is the cumulative number of all
+coordinates from the component geometries.
+
+``ring``
+^^^^^^^^
+.. attribute:: ring
+Returns a boolean indicating whether the geometry is a ``LinearRing``.
+
+``simple``
+^^^^^^^^^^
+.. attribute:: simple
+A Geometry is simple if and only if the only self-intersections are at boundary 
+points.  For example, a ``LineString`` object is not simple if it intersects 
+itself. Thus, ``LinearRing`` and ``Polygon`` objects are always simple because 
+they do not intersect themselves.
+
+``valid``
+^^^^^^^^^
+.. attribute:: valid
+Returns a boolean indicating whether the geometry is valid.
+
+Output Properties
+-----------------
+
+.. _ewkt:
+
+``ewkt``
+^^^^^^^^
+.. attribute:: ewkt
+Returns the "extended" Well-Known Text of the geometry.  This representation
+is specific to PostGIS and is a super set of the OGC WKT standard. [#]_
+Essentially the SRID is prepended to the WKT representation, for example 
+``SRID=4326;POINT(5 23)``.  Please note that this does not include 
+the 3dm, 3dz, and 4d information that PostGIS supports in its EWKT 
+representations.
+
+.. _hex:
+
+``hex``
+^^^^^^^
+.. attribute:: hex
+Returns the WKB of this Geometry in hexadecimal form.  Please note
+that the SRID and Z values are not included in this representation
+because it is not a part of the OGC specification (use the :ref:`hexewkb` 
+property instead).
+
+.. _hexewkb:
+
+``hexewkb``
+^^^^^^^^^^^
+.. versionadded:: 1.2
+.. attribute:: hexewkb
+
+Returns the EWKB of this Geometry in hexadecimal form.  This is an 
+extension of the WKB specification that includes SRID and Z values 
+that are a part of this geometry.
+
+.. note::
+
+   GEOS 3.1 is *required* if you want valid 3D HEXEWKB.
+
+``json``, ``geojson``
+^^^^^^^^^^^^^^^^^^^^^
+.. attribute:: json
+.. attribute:: geojson
+Returns the GeoJSON representation of the geometry.  Requires GDAL.
+
+``kml``
+^^^^^^^^^
+.. attribute:: kml
+Returns a `KML`__ (Keyhole Markup Language) representation of the
+geometry.  This should only be used for geometries with an SRID of 
+4326 (WGS84), but this restriction is not enforced.
+
+``ogr``
+^^^^^^^^
+.. attribute:: ogr
+Returns an OGR ``OGRGeometry`` object correspondg to the GEOS geometry.
+Consult the `OGRGeometry`_ documentation for more information.
+
+.. _OGRGeometry: gdal.html#ogrgeometry
+
+.. note::
+
+    Requires GDAL.
+
+.. _wkb:
+
+``wkb``
+^^^^^^^^
+.. attribute:: wkb
+Returns the WKB (Well-Known Binary) representation of this Geometry
+as a Python buffer.  SRID and Z values are not included, use the
+:ref:`ewkb` property instead.
+
+.. _ewkb:
+
+``ewkb``
+^^^^^^^^^
+.. attribute:: ewkb
+.. versionadded:: 1.2
+
+Return the EWKB representation of this Geometry as a Python buffer.
+This is an extension of the WKB specification that includes any SRID
+and Z values that are a part of this geometry.
+
+.. note::
+
+   GEOS 3.1 is *required* if you want valid 3D EWKB.
+
+``wkt``
+^^^^^^^^^
+.. attribute:: wkt
+Returns the Well-Known Text of the geometry (an OGC standard).
+
+__ http://code.google.com/apis/kml/documentation/
+
+Spatial Predicate Methods
+-------------------------
+All of the following spatial predicate methods take another GEOS Geometry 
+instance (``other``) as an argument.
+
+``contains(other)``
+^^^^^^^^^^^^^^^^^^^
+.. method:: contains(other)
+Returns True if ``within(other)`` is False.
+
+``crosses(other)``
+^^^^^^^^^^^^^^^^^^
+.. method:: crosses(other)
+Returns true if the DE-9IM intersection matrix for the two Geometries
+is ``T*T******`` (for a point and a curve,a point and an area or a line 
+and an area) ``0********`` (for two curves).
+
+``disjoint(other)``
+^^^^^^^^^^^^^^^^^^^
+.. method:: disjoint(other)
+Returns true if the DE-9IM intersection matrix for the two Geometries
+is ``FF*FF****``.
+
+``equals(other)``
+^^^^^^^^^^^^^^^^^
+.. method:: equals(other)
+Returns true if the DE-9IM intersection matrix for the two Geometries 
+is ``T*F**FFF*``.
+
+``equals_exact(other, tolerance=0)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. method:: equals_exact(other, tolerance=0)
+Returns true if the two Geometries are exactly equal, up to a
+specified tolerance.  The ``tolerance`` value should be a floating
+point number representing the error tolerance in the comparison, e.g.,
+``poly1.equals_exact(poly2, 0.001)`` will compare equality to within
+one thousandth of a unit.
+
+``intersects(other)``
+^^^^^^^^^^^^^^^^^^^^^
+.. method:: intersects(other)
+Returns True if ``disjoint(other)`` is False.
+
+``overlaps(other)``
+^^^^^^^^^^^^^^^^^^^
+.. method:: overlaps(other)
+Returns true if the DE-9IM intersection matrix for the two Geometries
+is ``T*T***T**`` (for two points or two surfaces) ``1*T***T**``
+(for two curves).
+
+``relate_pattern(other, pattern)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. method:: relate_pattern(other, pattern)
+Returns true if the elements in the DE-9IM intersection matrix 
+for this geometry and the other matches the given ``pattern`` -- 
+a string of nine characters from the alphabet: {``T``, ``F``, ``*``, ``0``}.
+
+``touches(other)``
+^^^^^^^^^^^^^^^^^^
+.. method:: touches(other)
+Returns true if the DE-9IM intersection matrix for the two Geometries
+is ``FT*******``, ``F**T*****`` or ``F***T****``.
+
+``within(other)``
+^^^^^^^^^^^^^^^^^
+.. method:: within(other)
+Returns true if the DE-9IM intersection matrix for the two Geometries
+is ``T*F**F***``.
+
+Topological Methods
+-------------------
+
+``buffer(width, quadsegs=8)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. method:: buffer(width, quadsegs=8)
+Returns a geometry that represents all points whose distance from this
+geometry is less than or equal to the given ``width``. The optional 
+``quadsegs`` keyword sets the number of segments used to approximate a 
+quarter circle (defaults is 8).
+
+``difference(other)``
+^^^^^^^^^^^^^^^^^^^^^
+.. method:: difference(other)
+Returns a geometry representing the points making up this geometry
+that do not make up other.
+
+``intersection(other)``
+^^^^^^^^^^^^^^^^^^^^^^^
+.. method:: intersection(other)
+Returns a geometry representing the points shared by this geometry and other.
+
+``relate(other)``
+^^^^^^^^^^^^^^^^^
+.. method:: relate(other)
+Returns the DE-9IM intersection matrix for this geometry and the other.
+
+``simplify(tolerance=0.0, preserve_topology=False)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. method:: simplify(tolerance=0.0, preserve_topology=False)
+Returns the geometry, simplified using the Douglas-Peucker algorithm
+to the specified tolerance (higher tolerance => less points).  If no
+tolerance provided, defaults to 0.
+
+By default, this function does not preserve topology - e.g. polygons can 
+be split, collapse to lines or disappear holes can be created or 
+disappear, and lines can cross. By specifying ``preserve_topology=True``, 
+the result will have the same dimension and number of components as the 
+input. This is significantly slower.   
+
+``sym_difference(other)``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+.. method:: sym_difference(other)
+Returns a set combining the points in this geometry not in other,
+and the points in other not in this geometry.
+
+``union(other)``
+^^^^^^^^^^^^^^^^
+.. method:: union(other)
+Returns a Geometry representing all the points in this Geometry and other.
+
+Topological Properties
+----------------------
+
+``boundary``
+^^^^^^^^^^^^
+.. attribute:: boundary
+Returns the boundary as a newly allocated Geometry object.
+
+``centroid``
+^^^^^^^^^^^^
+.. attribute:: centroid
+The centroid is equal to the centroid of the set of component Geometries
+of highest dimension (since the lower-dimension geometries contribute zero
+"weight" to the centroid).
+
+``convex_hull``
+^^^^^^^^^^^^^^^
+.. attribute:: convex_hull
+Returns the smallest convex Polygon that contains all the points in
+the Geometry.
+
+``envelope``
+^^^^^^^^^^^^
+.. attribute:: envelope
+Returns a ``Polygon`` that represents the bounding envelope of this geometry.
+
+``point_on_surface``
+^^^^^^^^^^^^^^^^^^^^
+.. attribute:: point_on_surface
+Computes and returns a ``Point`` guaranteed to be on the interior of this
+geometry.
+
+Other Properties & Methods
+--------------------------
+
+``extent``
+^^^^^^^^^^
+.. attribute:: extent
+This property returns the extent of this geometry as a 4-tuple, 
+consisting of (xmin, ymin, xmax, ymax).
+
+``area``
+^^^^^^^^
+.. attribute:: area
+This property returns the area of the Geometry.
+
+``distance(geom)``
+^^^^^^^^^^^^^^^^^^
+.. method:: distance(geom)
+Returns the distance between the closest points on this Geometry and the given
+``geom`` (another ``GEOSGeometry`` object).
+
+.. note::
+
+    GEOS distance calculations are  linear -- in other words, GEOS will not
+    perform a spherical calculation even if the SRID specifies a geographic 
+    coordinate system.
+
+``length``
+^^^^^^^^^^
+.. attribute:: length
+Returns the length of this Geometry (e.g., 0 for point or the
+circumference of a Polygon).
+
+``prepared``
+^^^^^^^^^^^^
+.. attribute:: prepared
+.. versionadded:: 1.1
+
+.. note::
+
+    Support for prepared geometries requires GEOS 3.1.
+
+Returns a GEOS ``PreparedGeometry`` for the contents of this geometry.  
+``PreparedGeometry`` objects are optimized for the contains, intersects,
+and covers operations.  Refer to the :ref:`prepared` documentation for
+more information.
+
+``srs``
+^^^^^^^
+.. attribute:: srs
+Returns an OGR ``SpatialReference`` object corresponding to the SRID of the 
+geometry or ``None``.  Consult the `SpatialReference documentation`_ for more
+information about these objects.
+
+.. _SpatialReference documentation: gdal.html#spatialreference
+
+.. note::
+
+    Requires GDAL.
+
+``transform(ct, clone=False)``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. method:: transform(ct, clone=False)
+Transforms the geometry according to the given transformation object, which may 
+be an integer SRID, spatial reference WKT string, a PROJ.4 string, or a 
+``SpatialReference`` object. By default, the geometry is transformed in-place and 
+nothing is returned. However if the `clone` keyword is set, then the geometry 
+is not modified and a transformed clone is returned instead.
+
+.. note::
+
+    GDAL and PROJ.4 are required to perform coordinate system transformations.
+
+.. rubric:: Footnotes
+.. [#] *See* Sean Gillies, `Geometries for Python <http://zcologia.com/news/150/geometries-for-python/>`_ (blog post explaining rationale for abandoning GEOS support); *see also* Sean's message on the `geos-devel mailing list <http://geos.refractions.net/pipermail/geos-devel/2007-March/002851.html>`_, Mar. 5, 2007
+.. [#] *See generally* `Python's ctypes documentation <http://docs.python.org/lib/module-ctypes.html>`_, at Ch. 14.14.
+.. [#] Specifically, ``GEOSGeometry`` was introduced in `revision 5008 <http://code.djangoproject.com/changeset/5008>`_ on April 15th, 2007.
+.. [#] *See* Sean Gillies, `Geometries for Python Update <http://zcologia.com/news/429/geometries-for-python-update/>`_, April 16th 2007 ("The ctypes-based geometry module in r5008 looks kickass. I'm checking it out now.").
+.. [#] Sean Gillies, `Proposal to launch the Shapely Project <http://lists.gispython.org/pipermail/community/2007-May/000953.html>`_, May 1, 2007.
+.. [#] Justin Bronn, `RE: Proposal to launch the Shapely project <http://lists.gispython.org/pipermail/community/2007-May/000964.html>`_, May 1, 2007.
+.. [#] Sean Gillies, `Proposal to change Shapely license from LGPL to BSD <http://lists.gispython.org/pipermail/community/2007-November/001271.html>`_, Nov. 20, 2007.
+.. [#] *See* `PostGIS EWKB, EWKT and Canonical Forms <http://postgis.refractions.net/docs/ch04.html#id2591381>`_, PostGIS documentation at Ch. 4.1.2.
+
Index: docs/ref/contrib/gis/create_template_postgis-1.3.sh
===================================================================
--- docs/ref/contrib/gis/create_template_postgis-1.3.sh	(revision 0)
+++ docs/ref/contrib/gis/create_template_postgis-1.3.sh	(revision 0)
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+POSTGIS_SQL_PATH=`pg_config --sharedir`
+createdb -E UTF8 template_postgis # Create the template spatial database.
+createlang -d template_postgis plpgsql # Adding PLPGSQL language support.
+psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';"
+psql -d template_postgis -f $POSTGIS_SQL_PATH/lwpostgis.sql # Loading the PostGIS SQL routines
+psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql
+psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables.
+psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"

Property changes on: docs/ref/contrib/gis/create_template_postgis-1.3.sh
___________________________________________________________________
Name: svn:executable
   + *

Index: docs/ref/contrib/gis/utils.txt
===================================================================
--- docs/ref/contrib/gis/utils.txt	(revision 0)
+++ docs/ref/contrib/gis/utils.txt	(revision 0)
@@ -0,0 +1,12 @@
+======================
+GeoDjango Utilities
+======================
+
+The ``django.contrib.gis.utils`` module contains various utilities that are
+useful in creating geospatial web applications.
+
+.. toctree::
+   :maxdepth: 2
+
+   geoip
+   layermapping
Index: docs/ref/contrib/index.txt
===================================================================
--- docs/ref/contrib/index.txt	(revision 12454)
+++ docs/ref/contrib/index.txt	(working copy)
@@ -32,6 +32,7 @@
    databrowse
    flatpages
    formtools/index
+   gis/index
    humanize
    localflavor
    messages
@@ -111,6 +112,13 @@
 
 See the :ref:`form wizard documentation <ref-contrib-formtools-form-wizard>`.
 
+gis
+====
+
+A world-class geospatial framework built on top of Django.
+
+Allows storage, manipulation and display of Geographic data.
+
 humanize
 ========
 
