Fixed #12930, #12832, #11538 -- Refactored and merged the GeoDjango documentation into the rest of the Django docs.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12856 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2010-03-26 20:14:53 +00:00
parent 667ced2abc
commit 459c71e332
25 changed files with 7101 additions and 5 deletions

View File

@ -0,0 +1,57 @@
.. _ref-gis-admin:
======================
GeoDjango's admin site
======================
.. module:: django.contrib.gis.admin
:synopsis: GeoDjango's extensions to the admin site.
``GeoModelAdmin``
=================
.. class:: GeoModelAdmin
.. attribute:: default_lon
The default center longitude.
.. attribute:: default_lat
The default center latitude.
.. attribute:: default_zoom
The default zoom level to use. Defaults to 18.
.. attribute:: extra_js
Sequence of URLs to any extra JavaScript to include.
.. attribute:: map_template
Override the template used to generate the JavaScript slippy map.
Default is ``'gis/admin/openlayers.html'``.
.. attribute:: map_width
Width of the map, in pixels. Defaults to 600.
.. attribute:: map_height
Height of the map, in pixels. Defaults to 400.
.. attribute:: openlayers_url
Link to the URL of the OpenLayers JavaScript. Defaults to
``'http://openlayers.org/api/2.8/OpenLayers.js'``.
``OSMGeoAdmin``
===============
.. class:: OSMGeoAdmin
A subclass of :class:`GeoModelAdmin` that uses a spherical mercator projection
with OpenStreetMap street data tiles. See the :ref:`OSMGeoAdmin introduction <osmgeoadmin-intro>`
in the tutorial for a usage example.

View File

@ -0,0 +1,83 @@
.. ref-geodjango-admin:
=============================
GeoDjango Management Commands
=============================
inspectdb
=========
.. describe:: django-admin.py inspectdb
When :mod:`django.contrib.gis` is in your :setting:`INSTALLED_APPS`, the
:djadmin:`inspectdb` management command is overridden with one from GeoDjango.
The overridden command is spatially-aware, and places geometry fields in the
auto-generated model definition, where appropriate.
ogrinspect <data_source> <model_name>
=====================================
.. django-admin:: ogrinspect
The ``ogrinpsect`` management command will inspect the given OGR-compatible
:class:`~django.contrib.gis.gdal.DataSource` (e.g., a shapefile) and will
output a GeoDjango model with the given model name. There's a detailed example
of using ``ogrinspect`` :ref:`in the tutorial <ogrinspect-intro>`.
.. django-admin-option:: --blank <blank_field(s)>
Use a comma separated list of OGR field names to add the ``blank=True``
keyword option to the field definition. Set with ``true`` to apply
to all applicable fields.
.. django-admin-option:: --decimal <decimal_field(s)>
Use a comma separated list of OGR float fields to generate
:class:`~django.db.models.DecimalField` instead of the default
:class:`~django.db.models.FloatField`. Set to ``true`` to apply to all
OGR float fields.
.. django-admin-option:: --geom-name <name>
Specifies the model attribute name to use for the geometry field.
Defaults to ``'geom'``.
.. django-admin-option:: --layer <layer>
The key for specifying which layer in the OGR
:class:`~django.contrib.gis.gdal.DataSource` source to use.
Defaults to 0 (the first layer). May be an integer or a string identifier
for the :class:`~django.contrib.gis.gdal.Layer`.
.. django-admin-option:: --mapping
Automatically generate a mapping dictionary for use with
:class:`~django.contrib.gis.utils.LayerMapping`.
.. django-admin-option:: --multi-geom
When generating the geometry field, treat it as a geometry collection.
For example, if this setting is enabled then a
:class:`~django.contrib.gis.db.models.MultiPolygonField` will be placed
in the generated model rather than
:class:`~django.contrib.gis.db.models.PolygonField`.
.. django-admin-option:: --name-field <name_field>
Generates a ``__unicode__`` routine on the model that will return the
the given field name.
.. django-admin-option:: --no-imports
Suppresses the ``from django.contrib.gis.db import models`` import statement.
.. django-admin-option:: --null <null_field(s)>
Use a comma separated list of OGR field names to add the ``null=True``
keyword option to the field definition. Set with ``true`` to apply to
all applicable fields.
.. django-admin-option:: --srid
The SRID to use for the geometry field. If not set, ``ogrinspect`` attempts
to automatically determine of the SRID of the data source.

View File

@ -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;"

View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib/postgis-1.4
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;"

View File

@ -0,0 +1,9 @@
#!/usr/bin/env bash
POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib/postgis-1.5
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;"

View File

@ -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;"

View File

@ -0,0 +1,304 @@
.. _ref-gis-db-api:
======================
GeoDjango Database API
======================
.. module:: django.contrib.gis.db.models
:synopsis: GeoDjango's database API.
.. _spatial-backends:
Spatial Backends
================
.. versionadded:: 1.2
In Django 1.2, support for :ref:`multiple databases <topics-db-multi-db>` was
introduced. In order to support multiple databases, GeoDjango has segregated
its functionality into full-fledged spatial database backends:
* :mod:`django.contrib.gis.db.backends.postgis`
* :mod:`django.contrib.gis.db.backends.mysql`
* :mod:`django.contrib.gis.db.backends.oracle`
* :mod:`django.contrib.gis.db.backends.spatialite`
Backwards-Compatibility
-----------------------
For those using the old database settings (e.g., the ``DATABASE_*`` settings)
Django 1.2 will automatically use the appropriate spatial backend as long
as :mod:`django.contrib.gis` is in your :setting:`INSTALLED_APPS`. For
example, if you have the following in your settings::
DATABASE_ENGINE='postgresql_psycopg2'
...
INSTALLED_APPS = (
...
'django.contrib.gis',
...
)
Then, :mod:`django.contrib.gis.db.backends.postgis` will automatically be used as your
spatial backend.
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()
:class:`~django.contrib.gis.geos.GEOSGeometry` objects may also be used to save geometric models::
>>> from django.contrib.gis.geos import GEOSGeometry
>>> poly = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
>>> z = Zipcode(code=77096, poly=poly)
>>> 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 [#fnwkt]_), HEXEWKB (PostGIS specific -- a WKB geometry in
hexadecimal [#fnewkb]_), and GeoJSON [#fngeojson]_ (requires GDAL). Essentially,
if the input is not a ``GEOSGeometry`` object, the geometry field will attempt to
create a ``GEOSGeometry`` instance from the input.
For more information creating :class:`~django.contrib.gis.geos.GEOSGeometry`
objects, refer to the :ref:`GEOS tutorial <geos-tutorial>`.
.. _spatial-lookups-intro:
Spatial Lookups
===============
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 on geometry fields.
Filters on 'normal' fields (e.g. :class:`~django.db.models.CharField`)
may be chained with those on geographic fields. Thus, geographic queries
take the following general form (assuming the ``Zipcode`` model used in the
:ref:`ref-gis-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, :lookup:`contains <gis-contains>`
is the spatial lookup type, and ``pnt`` is the parameter (which may be a
:class:`~django.contrib.gis.geos.GEOSGeometry` object or a string of
GeoJSON , WKT, or HEXEWKB).
A complete reference can be found in the :ref:`spatial lookup reference
<spatial-lookups>`.
.. note::
GeoDjango constructs spatial SQL with the :class:`GeoQuerySet`, a
subclass of :class:`~django.db.models.QuerySet`. The
:class:`GeoManager` instance attached to your model is what
enables use of :class:`GeoQuerySet`.
.. _distance-queries:
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 :ref:`selecting-an-srid` section
in the :ref:`ref-gis-model-api` documentation for more details.
.. _distance-lookups-intro:
Distance Lookups
----------------
*Availability*: PostGIS, Oracle, SpatiaLite
The following distance lookups are available:
* :lookup:`distance_lt`
* :lookup:`distance_lte`
* :lookup:`distance_gt`
* :lookup:`distance_gte`
* :lookup:`dwithin`
.. note::
For *measuring*, rather than querying on distances, use the
:meth:`GeoQuerySet.distance` method.
Distance lookups take a tuple parameter comprising:
#. A geometry to base calculations from; and
#. A number or :class:`~django.contrib.gis.measure.Distance` object containing the distance.
If a :class:`~django.contrib.gis.measure.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 are 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 [#fndistsphere]_. Thus,
geographic distance lookups on traditional PostGIS geometry columns are
only allowed on :class:`PointField` model fields using a point for the
geometry parameter.
.. note::
PostGIS 1.5 introduced :ref:`geography columns <geography-type>`, which
is limited on what geometry types distance queries are performed with. In
other words, if you have ``geography=True`` in your geometry field
definition you'll be allowed to peform arbitrary distance queries with your
data in geodetic units of WGS84.
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
.. _compatibility-table:
Compatibility Tables
====================
.. _spatial-lookup-compatibility:
Spatial Lookups
---------------
The following table provides a summary of what spatial lookups are available
for each spatial database backend.
================================= ========= ======== ============ ==========
Lookup Type PostGIS Oracle MySQL [#]_ SpatiaLite
================================= ========= ======== ============ ==========
:lookup:`bbcontains` X X X
:lookup:`bboverlaps` X X X
:lookup:`contained` X X X
:lookup:`contains <gis-contains>` X X X X
:lookup:`contains_properly` X
:lookup:`coveredby` X X
:lookup:`covers` X X
:lookup:`crosses` X X
:lookup:`disjoint` X X X X
:lookup:`distance_gt` X X X
:lookup:`distance_gte` X X X
:lookup:`distance_lt` X X X
:lookup:`distance_lte` X X X
:lookup:`dwithin` X X
:lookup:`equals` X X X X
:lookup:`exact` X X X X
:lookup:`intersects` X X X X
:lookup:`overlaps` X X X X
:lookup:`relate` X X X
:lookup:`same_as` X X X X
:lookup:`touches` X X X X
:lookup:`within` X X X X
:lookup:`left` X
:lookup:`right` X
:lookup:`overlaps_left` X
:lookup:`overlaps_right` X
:lookup:`overlaps_above` X
:lookup:`overlaps_below` X
:lookup:`strictly_above` X
:lookup:`strictly_below` X
================================= ========= ======== ============ ==========
.. _geoqueryset-method-compatibility:
``GeoQuerySet`` Methods
-----------------------
The following table provides a summary of what :class:`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
==================================== ======= ====== ==========
:meth:`GeoQuerySet.area` X X X
:meth:`GeoQuerySet.centroid` X X X
:meth:`GeoQuerySet.collect` X
:meth:`GeoQuerySet.difference` X X X
:meth:`GeoQuerySet.distance` X X X
:meth:`GeoQuerySet.envelope` X X
:meth:`GeoQuerySet.extent` X X
:meth:`GeoQuerySet.extent3d` X
:meth:`GeoQuerySet.force_rhr` X
:meth:`GeoQuerySet.geohash` X
:meth:`GeoQuerySet.geojson` X
:meth:`GeoQuerySet.gml` X X
:meth:`GeoQuerySet.intersection` X X X
:meth:`GeoQuerySet.kml` X
:meth:`GeoQuerySet.length` X X X
:meth:`GeoQuerySet.make_line` X
:meth:`GeoQuerySet.mem_size` X
:meth:`GeoQuerySet.num_geom` X X X
:meth:`GeoQuerySet.num_points` X X X
:meth:`GeoQuerySet.perimeter` X X
:meth:`GeoQuerySet.point_on_surface` X X X
:meth:`GeoQuerySet.reverse_geom` X X
:meth:`GeoQuerySet.scale` X X
:meth:`GeoQuerySet.snap_to_grid` X
:meth:`GeoQuerySet.svg` X X
:meth:`GeoQuerySet.sym_difference` X X X
:meth:`GeoQuerySet.transform` X X X
:meth:`GeoQuerySet.translate` X X
:meth:`GeoQuerySet.union` X X X
:meth:`GeoQuerySet.unionagg` X X X
==================================== ======= ====== ==========
.. rubric:: Footnotes
.. [#fnwkt] *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).
.. [#fnewkb] *See* `PostGIS EWKB, EWKT and Canonical Forms <http://postgis.refractions.net/documentation/manual-1.5/ch04.html#EWKB_EWKT>`_, PostGIS documentation at Ch. 4.1.2.
.. [#fngeojson] *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).
.. [#fndistsphere] *See* PostGIS 1.5 ``ST_distance_sphere`` `documentation <http://postgis.refractions.net/documentation/manual-1.5/ST_Distance_Sphere.html>`_.
.. [#] MySQL only supports bounding box operations (known as minimum bounding rectangles, or MBR, in MySQL). Thus, spatial lookups such as :lookup:`contains <gis-contains>` are really equivalent to :lookup:`bbcontains`.

View File

@ -0,0 +1,99 @@
===================
Deploying GeoDjango
===================
.. warning::
GeoDjango uses the GDAL geospatial library which is
not thread safe at this time. Thus, it is *highly* recommended
to not use threading when deploying -- in other words, use a
an appropriate configuration 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
:ref:`mod_wsgi documentation <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
:ref:`mod_python documentation <howto-deployment-modpython>`.
Lighttpd
========
FastCGI
-------
Nginx
=====
FastCGI
-------

View File

@ -0,0 +1,97 @@
.. _ref-gis-feeds:
================
Geographic Feeds
================
.. module:: django.contrib.gis.feeds
:synopsis: GeoDjango's framework for generating spatial feeds.
GeoDjango has its own :class:`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 <ref-contrib-syndication>`
for details on general usage.
.. _W3C Geo: http://www.w3.org/2003/01/geo/
__ http://georss.org/1.0#simple
Example
=======
API Reference
=============
``Feed`` Subclass
-----------------
.. class:: Feed
In addition to methods provided by
the :class:`django.contrib.syndication.feeds.Feed`
base class, GeoDjango's ``Feed`` class 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):
...
.. method:: 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).
.. method:: 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
------------------------------
The following :class:`django.utils.feedgenerator.SyndicationFeed` subclasses
are available:
.. class:: GeoRSSFeed
.. class:: GeoAtom1Feed
.. class:: W3CGeoFeed
.. note::
`W3C Geo`_ formatted feeds only support
:class:`~django.contrib.gis.db.models.PointField` geometries.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,223 @@
.. _ref-geoip:
======================
Geolocation with GeoIP
======================
.. module:: django.contrib.gis.utils.geoip
:synopsis: High-level Python interface for MaxMind's GeoIP C library.
.. currentmodule:: django.contrib.gis.utils
The :class:`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 :class:`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)'
``GeoIP`` Settings
==================
.. setting:: GEOIP_PATH
GEOIP_PATH
----------
A string specifying the directory where the GeoIP data files are
located. This setting is *required* unless manually specified
with ``path`` keyword when initializing the :class:`GeoIP` object.
.. setting:: GEOIP_LIBRARY_PATH
GEOIP_LIBRARY_PATH
------------------
A string specifying the location of the GeoIP C library. Typically,
this setting is only used if the GeoIP C library is in a non-standard
location (e.g., ``/home/sue/lib/libGeoIP.so``).
.. setting:: GEOIP_COUNTRY
GEOIP_COUNTRY
-------------
The basename to use for the GeoIP country data file.
Defaults to ``'GeoIP.dat'``.
.. setting:: GEOIP_CITY
GEOIP_CITY
----------
The basename to use for the GeoIP city data file.
Defaults to ``'GeoLiteCity.dat'``.
``GeoIP`` API
=============
.. class:: GeoIP([path=None, cache=0, country=None, city=None])
The ``GeoIP`` object does not require any parameters to use the default
settings. However, at the very least the :setting:`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 :setting:`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``).
``country`` The name of the GeoIP country data file. Defaults
to ``GeoIP.dat``. Setting this keyword overrides the
:setting:`GEOIP_COUNTRY` settings attribute.
``city`` The name of the GeoIP city data file. Defaults to
``GeoLiteCity.dat``. Setting this keyword overrides
the :setting:`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.
.. method:: GeoIP.city(query)
Returns a dictionary of city information for the given query. Some
of the values in the dictionary may be undefined (``None``).
.. method:: GeoIPcountry(query)
Returns a dictionary with the country code and country for the given
query.
.. method:: GeoIP.country_code(query)
Returns only the country code corresponding to the query.
.. method:: GeoIP.country_name(query)
Returns only the country name corresponding to the query.
Coordinate Retrieval
--------------------
.. method:: GeoIP.coords(query)
Returns a coordinate tuple of (longitude, latitude).
.. method:: GeoIP.lon_lat(query)
Returns a coordinate tuple of (longitude, latitude).
.. method:: GeoIP.lat_lon(query)
Returns a coordinate tuple of (latitude, longitude),
.. method:: GeoIP.geos(query)
Returns a :class:`django.contrib.gis.geos.Point` object corresponding to the query.
Database Information
--------------------
.. attribute:: GeoIP.country_info
This property returns information about the GeoIP country database.
.. attribute:: GeoIP.city_info
This property returns information about the GeoIP city database.
.. attribute:: GeoIP.info
This property returns information about all GeoIP databases (both city
and country).
GeoIP-Python API compatibility methods
----------------------------------------
These methods exist to ease compatibility with any code using MaxMind's
existing Python API.
.. classmethod:: GeoIP.open(path, cache)
This classmethod instantiates the GeoIP object from the given database path
and given cache setting.
.. method:: GeoIP.regioin_by_addr(query)
.. method:: GeoIP.region_by_name(query)
.. method:: GeoIP.record_by_addr(query)
.. method:: GeoIP.record_by_name(query)
.. method:: GeoIP.country_code_by_addr(query)
.. method:: GeoIP.country_code_by_name(query)
.. method:: GeoIP.country_name_by_addr(query)
.. method:: GeoIP.country_name_by_name(query)
.. rubric:: Footnotes
.. [#] GeoIP(R) is a registered trademark of MaxMind, LLC of Boston, Massachusetts.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,911 @@
.. _ref-geos:
========
GEOS API
========
.. module:: django.contrib.gis.geos
:synopsis: GeoDjango's high-level interface to the GEOS library.
Background
==========
What is GEOS?
-------------
`GEOS`__ stands for **G**\ eometry **E**\ ngine - **O**\ pen **S**\ ource,
and is a C++ library, ported from the `Java Topology Suite`__. GEOS
implements 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/
Features
--------
GeoDjango implements a high-level Python wrapper for the GEOS library, its
features include:
* A BSD-licensed interface to the GEOS geometry routines, implemented purely
in Python using ``ctypes``.
* Loosely-coupled to GeoDjango. For example, :class:`GEOSGeometry` objects
may be used outside of a django project/application. In other words,
no need to have ``DJANGO_SETTINGS_MODULE`` set or use a database, etc.
* Mutability: :class:`GEOSGeometry` objects may be modified.
* Cross-platform and tested; compatible with Windows, Linux, Solaris, and Mac
OS X platforms.
.. _geos-tutorial:
Tutorial
========
This section contains a brief introduction and tutorial to using
:class:`GEOSGeometry` objects.
Creating a Geometry
-------------------
:class:`GEOSGeometry` objects may be created in a few ways. The first is
to simply instantiate the object on some spatial input -- the following
are examples of creating the same geometry from WKT, HEX, WKB, and GeoJSON::
>>> from django.contrib.gis.geos import GEOSGeometry
>>> pnt = GEOSGeometry('POINT(5 23)') # WKT
>>> pnt = GEOSGeometry('010100000000000000000014400000000000003740') # HEX
>>> pnt = GEOSGeometry(buffer('\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14@\x00\x00\x00\x00\x00\x007@'))
>>> pnt = GEOSGeometry('{ "type": "Point", "coordinates": [ 5.000000, 23.000000 ] }') # GeoJSON
Another option is to use the constructor for the specific geometry type
that you wish to create. For example, a :class:`Point` object may be
created by passing in the X and Y coordinates into its constructor::
>>> from django.contrib.gis.geos import Point
>>> pnt = Point(5, 23)
Finally, there are :func:`fromstr` and :func:`fromfile` factory methods, which
return a :class:`GEOSGeometry` object from an input string or a file::
>>> from django.contrib.gis.geos import fromstr, fromfile
>>> pnt = fromstr('POINT(5 23)')
>>> pnt = fromfile('/path/to/pnt.wkt')
>>> pnt = fromfile(open('/path/to/pnt.wkt'))
Geometries are Pythonic
-----------------------
:class:`GEOSGeometry` objects are 'Pythonic', in other words components may
be accessed, modified, and iterated over using standard Python conventions.
For example, you can iterate over the coordinates in a :class:`Point`::
>>> pnt = Point(5, 23)
>>> [coord for coord in pnt]
[5.0, 23.0]
With any geometry object, the :attr:`GEOSGeometry.coords` property
may be used to get the geometry coordinates as a Python tuple::
>>> pnt.coords
(5.0, 23.0)
You can get/set geometry components using standard Python indexing
techniques. However, what is returned depends on the geometry type
of the object. For example, indexing on a :class:`LineString`
returns a coordinate tuple::
>>> from django.contrib.gis.geos import LineString
>>> line = LineString((0, 0), (0, 50), (50, 50), (50, 0), (0, 0))
>>> line[0]
(0.0, 0.0)
>>> line[-2]
(50.0, 0.0)
Whereas indexing on a :class:`Polygon` will return the ring
(a :class:`LinearRing` object) corresponding to the index::
>>> from django.contrib.gis.geos import Polygon
>>> poly = Polygon( ((0.0, 0.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (0.0, 0.0)) )
>>> poly[0]
<LinearRing object at 0x1044395b0>
>>> poly[0][-2] # second-to-last coordinate of external ring
(50.0, 0.0)
In addition, coordinates/components of the geometry may added or modified,
just like a Python list::
>>> line[0] = (1.0, 1.0)
>>> line.pop()
(0.0, 0.0)
>>> line.append((1.0, 1.0))
>>> line.coords
((1.0, 1.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (1.0, 1.0))
Geometry Objects
================
``GEOSGeometry``
----------------
.. class:: GEOSGeometry(geo_input[, srid=None])
:param geo_input: Geometry input value
:type geo_input: string or buffer
:param srid: spatial reference identifier
:type srid: integer
This is the base class for all GEOS geometry objects. It initializes on the
given ``geo_input`` argument, and then assumes the proper geometry subclass
(e.g., ``GEOSGeometry('POINT(1 1)')`` will create a :class:`Point` object).
The following input formats, along with their corresponding Python types,
are accepted:
============= ======================
Format Input Type
============= ======================
WKT / EWKT ``str`` or ``unicode``
HEX / HEXEWKB ``str`` or ``unicode``
WKB / EWKB ``buffer``
GeoJSON ``str`` or ``unicode``
============= ======================
Properties
~~~~~~~~~~
.. attribute:: GEOSGeometry.coords
Returns the coordinates of the geometry as a tuple.
.. attribute:: GEOSGeometry.empty
Returns whether or not the set of points in the geometry is empty.
.. attribute:: GEOSGeometry.geom_type
Returns a string corresponding to the type of geometry. For example::
>>> pnt = GEOSGeometry('POINT(5 23)')
>>> pnt.geom_type
'Point'
.. attribute:: GEOSGeometry.geom_typeid
Returns the GEOS geometry type identification number. The following table
shows the value for each geometry type:
=========================== ========
Geometry ID
=========================== ========
:class:`Point` 0
:class:`LineString` 1
:class:`LinearRing` 2
:class:`Polygon` 3
:class:`MultiPoint` 4
:class:`MultiLineString` 5
:class:`MultiPolygon` 6
:class:`GeometryCollection` 7
=========================== ========
.. attribute:: GEOSGeometry.num_coords
Returns the number of coordinates in the geometry.
.. attribute:: GEOSGeometry.num_geom
Returns the number of geometries in this geometry. In other words, will
return 1 on anything but geometry collections.
.. attribute:: GEOSGeometry.hasz
Returns a boolean indicating whether the geometry is three-dimensional.
.. attribute:: GEOSGeometry.ring
Returns a boolean indicating whether the geometry is a ``LinearRing``.
.. attribute:: GEOSGeometry.simple
Returns a boolean indicating whether the geometry is 'simple'. A geometry
is simple if and only if it does not intersect itself (except at boundary
points). For example, a :class:`LineString` object is not simple if it
intersects itself. Thus, :class:`LinearRing` and :class`Polygon` objects
are always simple because they do cannot intersect themselves, by
definition.
.. attribute:: GEOSGeometry.valid
Returns a boolean indicating whether the geometry is valid.
.. attribute:: GEOSGeometry.srid
Property that may be used to retrieve or set the SRID associated with the
geometry. For example::
>>> pnt = Point(5, 23)
>>> print pnt.srid
None
>>> pnt.srid = 4326
>>> pnt.srid
4326
Output Properties
~~~~~~~~~~~~~~~~~
The properties in this section export the :class:`GEOSGeometry` object into
a different. This output may be in the form of a string, buffer, or even
another object.
.. attribute:: GEOSGeometry.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. [#fnogc]_
Essentially the SRID is prepended to the WKT representation, for example
``SRID=4326;POINT(5 23)``.
.. note::
The output from this property does not include the 3dm, 3dz, and 4d
information that PostGIS supports in its EWKT representations.
.. attribute:: GEOSGeometry.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
:attr:`GEOSGeometry.hexewkb` property instead).
.. attribute:: GEOSGeometry.hexewkb
.. versionadded:: 1.2
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.
.. attribute:: GEOSGeometry.json
Returns the GeoJSON representation of the geometry.
.. note::
Requires GDAL.
.. attribute:: GEOSGeometry.geojson
Alias for :attr:`GEOSGeometry.json`.
.. attribute:: GEOSGeometry.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.
.. attribute:: GEOSGeometry.ogr
Returns an :class:`~django.contrib.gis.gdal.OGRGeometry` object
correspondg to the GEOS geometry.
.. note::
Requires GDAL.
.. _wkb:
.. attribute:: GEOSGeometry.wkb
Returns the WKB (Well-Known Binary) representation of this Geometry
as a Python buffer. SRID and Z values are not included, use the
:attr:`GEOSGeometry.ewkb` property instead.
.. _ewkb:
.. attribute:: GEOSGeometry.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.
.. attribute:: GEOSGeometry.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
:class:`GEOSGeometry` instance (``other``) as a parameter, and
return a boolean.
.. method:: GEOSGeometry.contains(other)
Returns ``True`` if :meth:`GEOSGeometry.within` is ``False``.
.. method:: GEOSGeometry.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).
.. method:: GEOSGeometry.disjoint(other)
Returns ``True`` if the DE-9IM intersection matrix for the two geometries
is ``FF*FF****``.
.. method:: GEOSGeometry.equals(other)
Returns ``True`` if the DE-9IM intersection matrix for the two geometries
is ``T*F**FFF*``.
.. method:: GEOSGeometry.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.
.. method:: GEOSGeometry.intersects(other)
Returns ``True`` if :meth:`GEOSGeometry.disjoint` is ``False``.
.. method:: GEOSGeometry.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).
.. method:: GEOSGeometry.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``}.
.. method:: GEOSGeometry.touches(other)
Returns ``True`` if the DE-9IM intersection matrix for the two geometries
is ``FT*******``, ``F**T*****`` or ``F***T****``.
.. method:: GEOSGeometry.within(other)
Returns ``True`` if the DE-9IM intersection matrix for the two geometries
is ``T*F**F***``.
Topological Methods
~~~~~~~~~~~~~~~~~~~
.. method:: GEOSGeometry.buffer(width, quadsegs=8)
Returns a :class:`GEOSGeometry` 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).
.. method:: GEOSGeometry.difference(other)
Returns a :class:`GEOSGeometry` representing the points making up this
geometry that do not make up other.
.. method:: GEOSGeometry:intersection(other)
Returns a :class:`GEOSGeometry` representing the points shared by this
geometry and other.
.. method:: GEOSGeometry.relate(other)
Returns the DE-9IM intersection matrix (a string) representing the
topological relationship between this geometry and the other.
.. method:: GEOSGeometry.simplify(tolerance=0.0, preserve_topology=False)
Returns a new :class:`GEOSGeometry`, simplified using the Douglas-Peucker
algorithm to the specified tolerance. A higher tolerance value implies
less points in the output. If no tolerance is tolerance provided,
it defaults to 0.
By default, this function does not preserve topology - e.g.,
:class:`Polygon` objects can be split, collapsed into lines or disappear.
:class:`Polygon` 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, however, this is
significantly slower.
.. method:: GEOSGeometry.sym_difference(other)
Returns a :class:`GEOSGeometry` combining the points in this geometry
not in other, and the points in other not in this geometry.
.. method:: GEOSGeometry.union(other)
Returns a :class:`GEOSGeometry` representing all the points in this
geometry and the other.
Topological Properties
~~~~~~~~~~~~~~~~~~~~~~
.. attribute:: GEOSGeometry.boundary
Returns the boundary as a newly allocated Geometry object.
.. attribute:: GEOSGeometry.centroid
Returns a :class:`Point` object representing the geometric center of
the geometry. The point is not guaranteed to be on the interior
of the geometry.
.. attribute:: GEOSGeometry.convex_hull
Returns the smallest :class:`Polygon` that contains all the points in
the geometry.
.. attribute:: GEOSGeometry.envelope
Returns a :class:`Polygon` that represents the bounding envelope of
this geometry.
.. attribute:: GEOSGeometry.point_on_surface
Computes and returns a :class:`Point` guaranteed to be on the interior
of this geometry.
Other Properties & Methods
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. attribute:: GEOSGeometry.area
This property returns the area of the Geometry.
.. attribute:: GEOSGeometry.extent
This property returns the extent of this geometry as a 4-tuple,
consisting of (xmin, ymin, xmax, ymax).
.. method:: GEOSGeometry.clone()
This method returns a :class:`GEOSGeometry` that is a clone of the original.
.. method:: GEOSGeometry.distance(geom)
Returns the distance between the closest points on this geometry and the given
``geom`` (another :class:`GEOSGeometry` object).
.. note::
GEOS distance calculations are linear -- in other words, GEOS does not
perform a spherical calculation even if the SRID specifies a geographic
coordinate system.
.. attribute:: GEOSGeometry.length
Returns the length of this geometry (e.g., 0 for a :class:`Point`,
the length of a :class:`LineString`, or the circumference of
a :class:`Polygon`).
.. attribute:: GEOSGeometry.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-geometries` documentation
for more information.
.. attribute:: GEOSGeometry.srs
Returns a :class:`~django.contrib.gis.gdal.SpatialReference` object
corresponding to the SRID of the geometry or ``None``.
.. note::
Requires GDAL.
.. method:: transform(ct, clone=False)
Transforms the geometry according to the given coordinate transformation paramter
(``ct``), which may be an integer SRID, spatial reference WKT string,
a PROJ.4 string, a :class:`~django.contrib.gis.gdal.SpatialReference` object, or a
:class:`~django.contrib.gis.gdal.CoordTransform` 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 of the geometry
is returned instead.
.. note::
Requires GDAL.
``Point``
---------
.. class:: Point(x, y, z=None, srid=None)
``Point`` objects are instantiated using arguments that represent
the component coordinates of the point or with a single sequence
coordinates. For example, the following are equivalent::
>>> pnt = Point(5, 23)
>>> pnt = Point([5, 23])
``LineString``
--------------
.. class:: LineString(*args, **kwargs)
``LineString`` objects are instantiated using arguments that are
either a sequence of coordinates or :class:`Point` objects.
For example, the following are equivalent::
>>> ls = LineString((0, 0), (1, 1))
>>> ls = LineString(Point(0, 0), Point(1, 1))
In addition, ``LineString`` objects may also be created by passing
in a single sequence of coordinate or :class:`Point` objects::
>>> ls = LineString( ((0, 0), (1, 1)) )
>>> ls = LineString( [Point(0, 0), Point(1, 1)] )
``LinearRing``
--------------
.. class:: LinearRing(*args, **kwargs)
``LinearRing`` objects are constructed in the exact same way as
:class:`LineString` objects, however the coordinates must be
*closed*, in other words, the first coordinates must be the
same as the last coordinates. For example::
>>> ls = LinearRing((0, 0), (0, 1), (1, 1), (0, 0))
Notice that ``(0, 0)`` is the first and last coordinate -- if
they were not equal, an error would be raised.
``Polygon``
-----------
.. class:: Polygon(*args, **kwargs)
``Polygon`` objects may be instantiated by passing in one or
more parameters that represent the rings of the polygon. The
parameters must either be :class:`LinearRing` instances, or
a sequence that may be used to construct a :class:`LinearRing`::
>>> ext_coords = ((0, 0), (0, 1), (1, 1), (1, 0), (0, 0))
>>> int_coords = ((0.4, 0.4), (0.4, 0.6), (0.6, 0.6), (0.6, 0.4), (0.4, 0.4))
>>> poly = Polygon(ext_coords, int_coords)
>>> poly = Polygon(LinearRing(ext_coords), LinearRing(int_coords))
.. classmethod:: from_bbox(bbox)
.. versionadded:: 1.1
Returns a polygon object from the given bounding-box, a 4-tuple
comprising (xmin, ymin, xmax, ymax).
.. attribute:: num_interior_rings
Returns the number of interior rings in this geometry.
Geometry Collections
====================
``MultiPoint``
--------------
.. class:: MultiPoint(*args, **kwargs)
``MultiPoint`` objects may be instantiated by passing in one
or more :class:`Point` objects as arguments, or a single
sequence of :class:`Point` objects::
>>> mp = MultiPoint(Point(0, 0), Point(1, 1))
>>> mp = MultiPoint( (Point(0, 0), Point(1, 1)) )
``MultiLineString``
-------------------
.. class:: MultiLineString(*args, **kwargs)
``MultiLineString`` objects may be instantiated by passing in one
or more :class:`LineString` objects as arguments, or a single
sequence of :class:`LineString` objects::
>>> ls1 = LineString((0, 0), (1, 1))
>>> ls2 = LineString((2, 2), (3, 3))
>>> mls = MultiLineString(ls1, ls2)
>>> mls = MultiLineString([ls1, ls2])
.. attribute:: merged
.. versionadded:: 1.1
Returns a :class:`LineString` representing the line merge of
all the components in this ``MultiLineString``.
``MultiPolygon``
----------------
.. class:: MultiPolygon(*args, **kwargs)
``MultiPolygon`` objects may be instantiated by passing one or
more :class:`Polygon` objects as arguments, or a single sequence
of :class:`Polygon` objects::
>>> p1 = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) )
>>> p2 = Polygon( ((1, 1), (1, 2), (2, 2), (1, 1)) )
>>> mp = MultiPolygon(p1, p2)
>>> mp = MultiPolygon([p1, p2])
.. attribute:: cascaded_union
.. versionadded:: 1.1
Returns a :class:`Polygon` that is the union of all of the component
polygons in this collection. The algorithm employed is significantly
more efficient (faster) than trying to union the geometries together
individually. [#fncascadedunion]_
.. note::
GEOS 3.1 is *required* to peform cascaded unions.
``GeometryCollection``
----------------------
.. class:: GeometryCollection(*args, **kwargs)
``GeometryCollection`` objects may be instantiated by passing in
one or more other :class:`GEOSGeometry` as arguments, or a single
sequence of :class:`GEOSGeometry` objects::
>>> poly = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) )
>>> gc = GeometryCollection(Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly)
>>> gc = GeometryCollection((Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly))
.. _prepared-geometries:
Prepared Geometries
===================
.. versionadded: 1.1
In order to obtain a prepared geometry, just access the
:attr:`GEOSGeometry.prepared` property. 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. For more information,
please consult the `GEOS wiki page on prepared geometries <http://trac.osgeo.org/geos/wiki/PreparedGeometry>`_.
.. 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 :class:`GEOSGeometry` instance.
.. method:: contains(other)
.. method:: contains_properly(other)
.. method:: covers(other)
.. method:: intersects(other)
Geometry Factories
==================
.. function:: fromfile(file_h)
:param file_h: input file that contains spatial data
:type file_h: a Python ``file`` object or a string path to the file
:rtype: a :class:`GEOSGeometry` corresponding to the spatial data in the file
Example::
>>> from django.contrib.gis.geos import fromfile
>>> g = fromfile('/home/bob/geom.wkt')
.. function:: fromstr(string, [,srid=None])
:param string: string that contains spatial data
:type string: string
:param srid: spatial reference identifier
:type srid: integer
:rtype: a :class:`GEOSGeometry` corresponding to the spatial data in the string
Example::
>>> from django.contrib.gis.geos import fromstr
>>> pnt = fromstr('POINT(-90.5 29.5)', srid=4326)
I/O Objects
===========
.. versionadded: 1.1
Reader Objects
--------------
The reader I/O classes simply return a :class:`GEOSGeometry` instance from the
WKB and/or WKT input given to their ``read(geom)`` method.
.. class:: WKBReader
Example::
>>> from django.contrib.gis.geos import WKBReader
>>> wkb_r = WKBReader()
>>> wkb_r.read('0101000000000000000000F03F000000000000F03F')
<Point object at 0x103a88910>
.. 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, :class:`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).
.. class:: WKBWriter
``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 allow for the creation of EWKB, a superset of the
WKB standard that includes additional information.
.. method:: WKBWriter.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>
.. method:: WKBWriter.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'
.. attribute:: WKBWriter.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'
.. attribute:: WKBWriter.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'
.. attribute:: WKBWriter.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'
.. class:: WKTWriter
.. method:: WKTWriter.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)'
.. rubric:: Footnotes
.. [#fnogc] *See* `PostGIS EWKB, EWKT and Canonical Forms <http://postgis.refractions.net/docs/ch04.html#id2591381>`_, PostGIS documentation at Ch. 4.1.2.
.. [#fncascadedunion] For more information, read Paul Ramsey's blog post about `(Much) Faster Unions in PostGIS 1.4 <http://blog.cleverelephant.ca/2009/01/must-faster-unions-in-postgis-14.html>`_ and Martin Davis' blog post on `Fast polygon merging in JTS using Cascaded Union <http://lin-ear-th-inking.blogspot.com/2007/11/fast-polygon-merging-in-jts-using.html>`_.
Settings
========
.. setting:: GEOS_LIBRARY_PATH
GEOS_LIBRARY_PATH
-----------------
A string specifying the location of the GEOS C library. Typically,
this setting is only used if the GEOS C library is in a non-standard
location (e.g., ``/home/bob/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``.

View File

@ -0,0 +1,33 @@
.. _ref-contrib-gis:
=========
GeoDjango
=========
.. versionadded:: 1.0
.. module:: django.contrib.gis
:synopsis: Geographic Information System (GIS) extensions for Django
GeoDjango intends to be a world-class geographic web framework. Its 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
geoquerysets
measure
geos
gdal
utils
commands
admin
feeds
sitemaps
testing
deployment

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,219 @@
.. _ref-layermapping:
====================================
``LayerMapping`` data import utility
====================================
.. module:: django.contrib.gis.utils.layermapping
:synopsis: Spatial data import utility for GeoDjango models.
.. currentmodule:: django.contrib.gis.utils
The :class:`LayerMapping` class provides a way to map the contents of
vector spatial data files (e.g. shapefiles) intoto GeoDjango models.
This utility grew out of the author's personal needs to eliminate
the code repetition that went into pulling geometries and fields out of
a vector layer, converting to another coordinate system (e.g. WGS84), and
then inserting into a GeoDjango model.
.. note::
Use of :class:`LayerMapping` requires GDAL.
.. warning ::
GIS data sources, like shapefiles, may be very large. If you find
that :class:`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 'Polygon'
Polygon
>>> print layer.srs # WGS84 in WKT
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 __unicode__(self):
return 'Name: %s' % self.name
3. Use :class:`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
Here, :class:`LayerMapping` just transformed the three geometries from the
shapefile in their original 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
:class:`django.contrib.gis.gdal.SpatialReference` object to specify one.
``LayerMapping`` API
====================
.. class:: LayerMapping(model, data_source, mapping[, layer=0, source_srs=None, encoding=None, transaction_mode='commit_on_success', transform=True, unique=True, using='default'])
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
:class:`django.contrib.gis.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
:class:`django.contrib.gis.gdal.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'``.
``using`` New in version 1.2. Sets the database to use when
importing spatial data. Default is ``'default'``
===================== =====================================================
``save()`` Keyword Arguments
----------------------------
.. method:: LayerMapping.save([verbose=False, fid_range=False, step=False, progress=False, silent=False, stream=sys.stdout, strict=False])
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

View File

@ -0,0 +1,180 @@
.. _ref-measure:
===================
Measurement Objects
===================
.. module:: django.contrib.gis.measure
:synopsis: GeoDjango's distance and area measurment objects.
The :mod:`django.contrib.gis.measure` module contains objects that allow
for convenient representation of distance and area units of measure. [#]_
Specifically, it implements two objects, :class:`Distance` and
:class:`Area` -- both of which may be accessed via the
:class:`D` and :class:`A` convenience aliases, respectively.
Example
=======
:class:`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 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 :class:`Distance` objects multiplied together will yield an :class:`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:
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
================================= ========================================
.. note::
:class:`Area` attributes are the same as :class:`Distance` attributes,
except they are prefixed with ``sq_`` (area units are square in nature).
For example, ``Area(sq_m=2)`` creates an :class:`Area` object
representing two square meters.
Measurement API
===============
``Distance``
------------
.. class:: Distance(**kwargs)
To initialize a distance object, pass in a keyword corresponding to
the desired :ref:`unit attribute name <supported_units>` set with
desired value. For example, the following creates a distance
object representing 5 miles::
>>> dist = Distance(mi=5)
.. method:: __getattr__(unit_att)
Returns the distance value in units corresponding to the given unit
attribute. For example::
>>> print dist.km
8.04672
.. classmethod:: unit_attname(unit_name)
Returns the distance unit attribute name for the given full unit name.
For example::
>>> Distance.unit_attname('Mile')
'mi'
.. class:: D
Alias for :class:`Distance` class.
``Area``
--------
.. class:: Area(**kwargs)
To initialize a distance object, pass in a keyword corresponding to
the desired :ref:`unit attribute name <supported_units>` set with
desired value. For example, the following creates a distance
object representing 5 square miles::
>>> a = Area(sq_mi=5)
.. method:: __getattr__(unit_att)
Returns the area value in units corresponding to the given unit
attribute. For example::
>>> print a.sq_km
12.949940551680001
.. classmethod:: unit_attname(unit_name)
Returns the area unit attribute name for the given full unit name.
For example::
>>> Area.unit_attname('Kilometer')
'sq_km'
.. class:: A
Alias for :class:`Area` class.
.. 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://code.google.com/p/geopy/>`_
and Geoff Biggs' PhD work on dimensioned units for robotics.

View File

@ -0,0 +1,266 @@
.. _ref-gis-model-api:
===================
GeoDjango Model API
===================
.. module:: django.contrib.gis.db.models
:synopsis: GeoDjango model and field 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
====================
Each of the following geometry field types correspond with the
OpenGIS Simple Features specification [#fnogc]_.
``GeometryField``
-----------------
.. class:: GeometryField
``PointField``
--------------
.. class:: PointField
``LineStringField``
-------------------
.. class:: LineStringField
``PolygonField``
----------------
.. class:: PolygonField
``MultiPointField``
-------------------
.. class:: MultiPointField
``MultiLineStringField``
------------------------
.. class:: MultiLineStringField
``MultiPolygonField``
---------------------
.. class:: MultiPolygonField
``GeometryCollectionField``
---------------------------
.. class:: GeometryCollectionField
.. _geometry-field-options:
Geometry Field Options
======================
In addition to the regular :ref:`common-model-field-options` available for
Django model fields, geometry fields have the following additional options.
All are optional.
``srid``
--------
.. attribute:: GeometryField.srid
Sets the SRID [#fnogcsrid]_ (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).
__ http://en.wikipedia.org/wiki/WGS84
.. _selecting-an-srid:
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. [#fnsrid]_ 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. [#fnharvard]_ 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`__. [#fnthematic]_ 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. [#fndist]_
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.
.. note::
If you wish to peform arbitrary distance queries using non-point
geometries, consider using PostGIS 1.5 and enabling the
:attr:`GeometryField.geography` keyword to use the
:ref:`geography database type <geography-type>` instead.
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
``spatial_index``
-----------------
.. attribute:: GeometryField.spatial_index
Defaults to ``True``. Creates a spatial index for the given geometry
field.
.. note::
This is different from the ``db_index`` field option because spatial
indexes are created in a different manner than regular database
indexes. Specifically, spatial indexes are typically created using
a variant of the R-Tree, while regular database indexes typically
use B-Trees.
``dim``
-------
.. versionadded:: 1.2
.. attribute:: GeometryField.dim
This option may be used for customizing the coordinate dimension of the
geometry field. By default, it is set to 2, for representing two-dimensional
geometries. For spatial backends that support it, it may be set to 3 for
three-dimensonal support.
.. note::
At this time 3D support requires that GEOS 3.1 be installed, and is
limited only to the PostGIS spatial backend.
``geography``
-------------
.. versionadded:: 1.2
.. attribute:: GeometryField.geography
If set to ``True``, this option will use create a database column of
type geography, rather than geometry. Please refer to the
:ref:`geography type <geography-type>` section below for more
details.
.. note::
Geography support is limited only to PostGIS 1.5+, and will
force the SRID to be 4326.
.. _geography-type:
Geography Type
^^^^^^^^^^^^^^
In PostGIS 1.5, the geography type was introduced -- it provides
provides native support for spatial features represented with geographic
coordinates (e.g., WGS84 longitude/latitude). [#fngeography]_
Unlike the plane used by a geometry type, the geography type uses a spherical
representation of its data. Distance and measurement operations
performed on a geography column automatically employ great circle arc
calculations and return linear units. In other words, when ``ST_Distance``
is called on two geographies, a value in meters is returned (as opposed
to degrees if called on a geometry column in WGS84).
Because geography calculations involve more mathematics, only a subset of the
PostGIS spatial lookups are available for the geography type. Practically,
this means that in addition to the :ref:`distance lookups <distance-lookups>`
only the following additional :ref:`spatial lookups <spatial-lookups>` are
available for geography columns:
* :lookup:`bboverlaps`
* :lookup:`exact`, and :lookup:`same_as`
* :lookup:`coveredby`
* :lookup:`covers`
* :lookup:`intersects`
For more information, the PostGIS documentation contains a helpful section on
determining `when to use geography data type over geometry data type
<http://postgis.refractions.net/documentation/manual-1.5/ch04.html#PostGIS_GeographyVSGeometry>`_.
``GeoManager``
==============
.. currentmodule:: django.contrib.gis.db.models
.. class:: 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
.. [#fnogc] OpenGIS Consortium, Inc., `Simple Feature Specification For SQL <http://www.opengis.org/docs/99-049.pdf>`_, Document 99-049 (May 5, 1999).
.. [#fnogcsrid] *See id.* at Ch. 2.3.8, p. 39 (Geometry Values and Spatial Reference Systems).
.. [#fnsrid] 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.
.. [#fnharvard] 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.
.. [#fnthematic] 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.
.. [#fndist] 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.
.. [#fngeography] Please refer to the `PostGIS Geography Type <http://postgis.refractions.net/documentation/manual-1.5/ch04.html#PostGIS_Geography>`_ documentation for more details.

View File

@ -0,0 +1,20 @@
.. _ref-ogrinspect:
==============
OGR Inspection
==============
.. module:: django.contrib.gis.utils.ogrinspect
:synopsis: Utilities for inspecting OGR data sources.
.. currentmodule:: django.contrib.gis.utils
``ogrinspect``
==============
.. function:: ogrinspect(data_source, model_name[, **kwargs])
``mapping``
===========
.. function:: mapping(data_source, [geom_name='geom', layer_key=0, multi_geom=False])

View File

@ -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>`_.

View File

@ -0,0 +1,181 @@
======================
Testing GeoDjango Apps
======================
.. versionchanged:: 1.2
In Django 1.2, the addition of :ref:`spatial-backends`
simplified the process of testing GeoDjango applications. Specifically, testing
GeoDjango applications is now the same as :ref:`topics-testing`.
Included in this documentation are some additional notes and settings
for :ref:`testing-postgis` and :ref:`testing-spatialite` users.
.. note::
Django 1.1 users are still required to use a custom :setting:`TEST_RUNNER`.
See the :ref:`testing-1.1` section for more details.
.. _testing-postgis:
PostGIS
=======
Settings
--------
.. note::
The settings below have sensible defaults, and shouldn't require manual setting.
.. setting:: POSTGIS_TEMPLATE
``POSTGIS_TEMPLATE``
^^^^^^^^^^^^^^^^^^^^
.. versionadded:: 1.1
.. versionchanged:: 1.2
This setting may be used to customize the name of the PostGIS template
database to use. In Django versions 1.2 and above, it automatically
defaults to ``'template_postgis'`` (the same name used in the
:ref:`installation documentation <spatialdb_template>`).
.. note::
Django 1.1 users will still have to define the :setting:`POSTGIS_TEMPLATE`
with a value, for example::
POSTGIS_TEMPLATE='template_postgis'
.. setting:: POSTGIS_VERSION
``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
:ref:`spatial database template <spatialdb_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 database 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 entitled ``template_postgis``.
.. _testing-spatialite:
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``,
then all you have to do is::
$ python manage.py test
Settings
--------
.. setting:: SPATIALITE_SQL
``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
.. _testing-1.1:
Testing GeoDjango Applications in 1.1
=====================================
In Django 1.1, to accommodate the extra steps required to scaffalod a
spatial database automatically, a test runner customized for GeoDjango
must be used. To use this runner, configure :setting:`TEST_RUNNER` as follows::
TEST_RUNNER='django.contrib.gis.tests.run_tests'
.. note::
In order to create a spatial database, the :setting:`DATABASE_USER` setting
(or :setting:`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.
GeoDjango Test Suite
====================
To run GeoDjango's own internal test suite, configure the
:setting:`TEST_RUNNER` setting as follows::
TEST_RUNNER='django.contrib.gis.tests.run_gis_tests'

View File

@ -0,0 +1,758 @@
==================
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.
* 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.
* Editing of geometry fields inside the admin.
This tutorial assumes a familiarity with Django; thus, if you're brand new to
Django please read through the :ref:`regular tutorial <intro-tutorial01>` to introduce
yourself with basic Django concepts.
.. note::
GeoDjango has special prerequisites overwhat is required by Django --
please consult the :ref:`installation documentation <ref-gis-install>`
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/
.. _world borders: http://thematicmapping.org/downloads/world_borders.php
.. _GeoDjango basic apps: http://code.google.com/p/geodjango-basic-apps/
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 :ref:`spatial database template <spatialdb_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 :ref:`SpatiaLite database <create_spatialite_db>`.
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::
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': 'geodjango',
'USER': 'geo',
}
}
.. note::
These database settings are for Django 1.2 and above.
In addition, modify the :setting:`INSTALLED_APPS` setting to include
:mod:`django.contrib.admin`, :mod:`django.contrib.gis`,
and ``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',
'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.
On GNU/Linux platforms the following commands should do it::
$ 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 :mod:`django.contrib.gis.db`.
2. The model overrides its default manager with
:class:`~django.contrib.gis.db.models.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 :ref:`ref-layermapping`.
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.
.. _ogr2ogr: http://www.gdal.org/ogr/ogr2ogr.html
.. _shp2pgsql: http://postgis.refractions.net/documentation/manual-1.5/ch04.html#shp2pgsql_usage
.. _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
:class:`~django.contrib.gis.gdal.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 :class:`~django.contrib.gis.gdal.Layer` may also have a spatial reference
system associated with it -- if it does, the ``srs`` attribute will return a
:class:`~django.contrib.gis.gdal.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
:class:`~django.contrib.gis.gdal.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()
.. _ogrinspect-intro:
Try ``ogrinspect``
------------------
Now that you've seen how to define geographic models and import data with the
:ref:`ref-layermapping`, it's possible to further automate this process with
use of the :djadmin:`ogrinspect` management command. The :djadmin:`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 [options] <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 :class:`~django.contrib.gis.utils.LayerMapping`.
* The ``--multi`` option is specified so that the geographic field is a
:class:`~django.contrib.gis.db.models.MultiPolygonField` instead of just a
:class:`~django.contrib.gis.db.models.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 :ref:`GEOS geometry object <ref-geos>` 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 :ref:`ref-gis-db-api` documentation has more.
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 <ref-geos>`,
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
----------------
GeoDjango extends :ref:`Django's admin application <ref-contrib-admin>` to
enable support for editing geometry fields.
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/(.*)', include(admin.site.urls)),
)
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/
.. _Open Street Map: http://openstreetmap.org/
.. _Vector Map Level 0: http://earth-info.nga.mil/publications/vmap0.html
.. _Metacarta: http://metacarta.com
.. _osmgeoadmin-intro:
``OSMGeoAdmin``
^^^^^^^^^^^^^^^
With the :class:`~django.contrib.gis.admin.OSMGeoAdmin`, GeoDjango uses
a `Open Street Map`_ layer in the admin.
This provides more context (including street and thoroughfare details) than
available with the :class:`~django.contrib.gis.admin.GeoModelAdmin`
(which uses the `Vector Map Level 0`_ WMS data set hosted at `Metacarta`_).
First, there are some important requirements and limitations:
* :class:`~django.contrib.gis.admin.OSMGeoAdmin` requires that the
:ref:`spherical mercator projection be added <addgoogleprojection>`
to the to be added to the ``spatial_ref_sys`` table (PostGIS 1.3 and
below, only).
* The PROJ.4 datum shifting files must be installed (see the
:ref:`PROJ.4 installation instructions <proj4>` 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.

View File

@ -0,0 +1,32 @@
.. _ref-gis-utils:
===================
GeoDjango Utilities
===================
.. module:: django.contrib.gis.utils
:synopsis: GeoDjango's collection of utilities.
The :mod:`django.contrib.gis.utils` module contains various utilities that are
useful in creating geospatial web applications.
.. toctree::
:maxdepth: 2
geoip
layermapping
ogrinspect
GeoIP
=====
Interface to the MaxMind GeoIP library for performing IP-based geolocation
from GeoDjango. See :ref:`GeoIP reference <ref-geoip>` documentation for
more information.
LayerMapping
============
The :class:`~django.contrib.gis.utils.LayerMapping` simplifies the process
of importing spatial data and attributes into your GeoDjango models.

View File

@ -32,6 +32,7 @@ those packages have.
databrowse
flatpages
formtools/index
gis/index
humanize
localflavor
messages
@ -111,6 +112,14 @@ Splits forms across multiple Web pages.
See the :ref:`form wizard documentation <ref-contrib-formtools-form-wizard>`.
gis
====
A world-class geospatial framework built on top of Django, that enables
storage, manipulation and display of spatial data.
See the :ref:`ref-contrib-gis` documentation for more.
humanize
========

View File

@ -296,11 +296,12 @@ manager that Django creates for you -- either as a default manager on a model
with no managers, or to use temporarily when accessing related objects.
Sometimes this default class won't be the right choice. One example is in the
`django.contrib.gis` application that ships with Django itself. All `gis`
models must use a special manager class (``GeoManager``) because they need a
special queryset (``GeoQuerySet``) to be used for interacting with the
database. It turns out that models which require a special manager like this
need to use the same manager class wherever an automatic manager is created.
:mod:`django.contrib.gis` application that ships with Django itself. All ``gis``
models must use a special manager class (:class:`~django.contrib.gis.db.models.GeoManager`)
because they need a special queryset (:class:`~django.contrib.gis.db.models.GeoQuerySet`)
to be used for interacting with the database. It turns out that models which require
a special manager like this need to use the same manager class wherever an automatic
manager is created.
Django provides a way for custom manager developers to say that their manager
class should be used for automatic managers whenever it is the default manager