Version 100 (modified by 17 years ago) ( diff ) | ,
---|
GeoDjango
TOC(GeoDjangoBackground, GeoDjango, GeoDjangoInstall, GeoDjangoModelAPI, GeoDjangoDatabaseAPI, GEOSGeometry, GeoDjangoExtras) The GIS branch intends to be a world-class geographic web framework. Our goal is to make it as easy as possible to build GIS web applications and harness the power of spatially enabled data.
News: The project was presented at FOSS4G 2007 on September 25, 2007. Thanks again for your support!
Note: The documentation has been re-factored into several pages. See the table of contents on the right for a complete listing of topics. Other GeoDjango pages include:
- Background Information
- Installation Instructions
- Model API
- Database API
- GEOS Geometries (in progress).
- Extra Features (in progress).
This documentation is behind the current feature-set -- when in doubt use help
on the feature in question, as most [browser:django/branches/gis/django/contrib/gis GeoDjango modules] and routines have docstrings.
Roadmap
Note: In order to minimize confusion, please don't modify the official roadmap below. If you have a suggestion, place it in the suggestion section or ask your question in the FAQ. If your request is urgent, submit a ticket requesting your feature or bugfix (make sure to specify the component as 'GIS'). Thanks for your cooperation!
Pending Features
The following is a discussion of features we hope to implement in GeoDjango. Unless stated otherwise, features in this list are not prioritized. If you have a pet feature you may accelerate its development by submitting code yourself.
- Distance queries, calculations, and related utilities. Status:
- Robert Coup has contributed the excellent measure module (in
django.contrib.gis.measure
), allowing for easy comparison of distances in a variety of formats (currently supported: feet, meters, yards, kilometers, miles, and nautical miles) - No support in the database API yet, but performing spatial queries using output from the GEOS
buffer()
function may tide you over until we implement full support.
- Robert Coup has contributed the excellent measure module (in
- Support for a mapping framework (e.g., Google Maps/Earth, Yahoo Maps, MS Live, etc.)
- Admin fields and forms (WKT field currently as of r4884, but we want widgets to view and manipulate geographic objects).
- WMS views.
- Add as much from the PostGIS API as possible.
- Support additional spatial databases, in the following order of priority.
- DB2
- When IBM DB2 Python DB-API adapter is available, work will commence on a spatial backend for DB2 Spatial Extender add-on. See Antonio Cagiano, Python, Django and DB2 Status Update blog posting.
- MySQL
- MySQL is last because its spatial offerings are not compliant with either the OGC and SQL/MM specifications. Specifically, all operations are limited to the bounding boxes of the geometries.
- DB2
- Geocoding framework.
Milestones
Significant GeoDjango changesets are mentioned below:
- r4851: Added PostGIS indexing capability.
- r5008: Added a
ctypes
interface for GEOS in [source:django/branches/gis/django/contrib/gis/gdal django.contrib.gis.geos].GEOSGeometry
: Wraps GEOS geometries; all accessed geometry fields are returned asGEOSGeometry
instances.
- r5397: Added a
ctypes
interface for GDAL/OGR in [source:django/branches/gis/django/contrib/gis/gdal django.contrib.gis.gdal].OGRGeometry
: Wraps OGR geometries, may be accessed with an extra instance method (e.g.,z.get_poly_ogr()
).SpatialReference
: Wraps OGR Spatial Reference objects, may be used to transform OGR geometries.DataSource
: Wraps OGR Data Source objects, may be used to explore GDAL-supported data sources
- r5529: Added utilities for importing vector data (e.g., SHP files) directly into GeoDjango models.
- The [source:django/branches/gis/django/contrib/gis/utils/LayerMapping.py LayerMapping] class will import vector data from GDAL-supported data sources. This is still 'beta', and requires installation of the GDAL library.
- r5657: "Lazy-Geometry" support was added (courtesy of Robert Coup's excellent patch in #4322) -- deprecating most of the extra instance methods.
- r6497: the
GeoMixin
was completely deprecated. - r6524: Oracle Spatial backend added.
Implementation
Design Issues
- Client JS/Flash framework. A
maps
module will be added soon, support for the following APIs will be implemented, or is being considereddjango.contrib.gis.maps.google
: This forthcoming module will containGoogleMap
object, which generates basic Google Maps API JavaScript from customizable templates. Automatic zoom-level determination of geometries will be included.django.contrib.gis.maps.openlayers
: Work will begin on a similar JavaScript utility for OpenLayers, which is the open source web mapping framework. Well-tested, BSD-licensed, and includes multitudes of features; for example, OpenLayers supports WMS/WFS/tiles as well as Google, MS Virtual Earth, and Yahoo layers.- Yahoo! has a really slick flash interface, I'd like to support this eventually, though not planned at this time.
- Mapping Framework (generating custom tiles, layers, labels, etc.)
- Mapnik is modern, but very early on in development and completely lacks documentation. However, the code is elegant and clean, and it was designed for integration with Python. First to use AGG rendering.
- Mapserver is the leading open source map renderer. MapServer is documented and has a strong and has strong community support. Uses text-based configuration files, which may be difficult to set up. AGG rendering and dynamic loading of configuration files (e.g., from a string) has been added to version 5.0.
- WMS Server
- I'm not satisfied with any of the current WMS/WFS implementations. One implemented in Django would be desirable, e.g.,
django.contrib.gis.wms
. Thoughts anyone? (OWSLib looks good, see below)
- I'm not satisfied with any of the current WMS/WFS implementations. One implemented in Django would be desirable, e.g.,
Collaboration
- PCL (Python Cartographic Library), now part of GIS Python, has done a lot of good work already. Let's apply the DRY principle. Strong opportunities for collaboration with regards to:
- Mapping framework
- WMS/WMF Framework -- OWSLib looks excellent for this (BSD licensed and has unit tests!)
- Utilities
- Database representation ideas
- GEOS support, Sean Gillies (of PCL) was the maintainer of the old SWIG bindings, and is working on ShapeLy, a GeoDjango-inspired GEOS ctypes interface.
- CoordinatesField.
- Jannis Leidel has already come up with a way to manipulate points in the admin interface, BSD licensed.
- geopy
- Brian Beck has written a good foundation for geocoding and distance calculations, BSD licensed.
Suggestions
- Decide what to do about "invalid" shape files, for example, float SHP field with ' ' value.
- Geo field introspection.
FAQ
- Place your questions here.
- Q: When dealing with points (say, degrees) from, do they need to be converted to be useful on the back-end data, assuming -that- data is in degrees? Is it enough to have the same datum and origin? (Reading the intro above is likely to answer the question.)
- My (JDunck) reading indicates yes. Given the same coordinate system (i.e. datum, origin, and axes), degrees are useful without conversion.
- Q: Can this implementation work with MySQL spatial-extensions. If not, it's planned?
- No, unfortunately support is not planned because MySQL's complete support of spatial queries will not be available until 7.0 (see my email to postgis-users for more details). As a spatial database PostGIS it is standards compliant (OpenGIS consortium), more widely used, and has more features (e.g., coordinate transformation,
geometry_columns
andspatial_ref_sys
tables). Until this situation improves, MySQL spatial support will not be a priority, but, I'm open to committing a user-contributed spatial backend for MySQL's current limited spatial offerings.
- No, unfortunately support is not planned because MySQL's complete support of spatial queries will not be available until 7.0 (see my email to postgis-users for more details). As a spatial database PostGIS it is standards compliant (OpenGIS consortium), more widely used, and has more features (e.g., coordinate transformation,
- Q: Is this going to be a WMS Server/WMS Client/Both? OWSLib is just a WMS Client from what I have seen (from ruckc)
- WMS Server first, client capability a possibility in certain situations (i.e. you want to cache data from another WMS server). Yes, OWSLib is a client, but it contains code for validating the correct parameters to send to a WMS server, thus it can be adapted into a Django view that validates whether the proper WMS parameters were given. Mapnik has an
ogcserver
module that can parse the correct parameters for WMS 1.1.1 and 1.3.0, however since it is licensed under the LGPL it cannot be easily incorporated into this branch (unlike OWSLib).
- WMS Server first, client capability a possibility in certain situations (i.e. you want to cache data from another WMS server). Yes, OWSLib is a client, but it contains code for validating the correct parameters to send to a WMS server, thus it can be adapted into a Django view that validates whether the proper WMS parameters were given. Mapnik has an
- Q: Per this discussion in
django-developers
, "I can do spatial queries if they are directly between two models with polygon fields but I can't seem to get at the spatial queries through foreign keys."- Geographic queries require
GeoManager
, even if the model does not have a geographic field itself (in the case of a foreign key to a geo-field). The reply in the discussion gives detail into why.
- Geographic queries require
- Q: Why are the OGRGeometry methods
transform
andtransform_to
separate?- Because these map to the separate OGR routines OGR_G_Transform and OGR_G_TransformTo. Specifically, the
transform
routine takes a CoordTransform object as a parameter, whereas thetransform_to
routine takes a SpatialReference object. Thetransform_to
"function requires internal creation and initialization of [a CoordTransform] object [and] it is significantly more expensive to use this function to transform many geometries than it is to create the [CoordTransform object] in advance, and call transform() with that transformation. This function exists primarily for convenience when only transforming a single geometry."
- Because these map to the separate OGR routines OGR_G_Transform and OGR_G_TransformTo. Specifically, the
Example
Geographic Models
Here is an example of how the model API currently works (assume this example is in geoapp/models.py):
from django.contrib.gis.db import models class District(models.Model): name = models.CharField(maxlength=35) num = models.IntegerField() poly = models.PolygonField() objects = models.GeoManager() class School(models.Model): name = models.CharField(maxlength=35) point = models.PointField() objects = models.GeoManager()
Notes: The GeoMixin
syntax is no longer needed as of r6467. By default, a GiST index will be created for the School PointField
s fields. This behavior can be turned off by using models.PointField(index=False)
.
Using syncdb
Both manage.py
commands sqlall
and syncdb
work on geographic models:
$ python manage.py sqlall geoapp
BEGIN; CREATE TABLE "geoapp_school" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(35) NOT NULL ) ; CREATE TABLE "geoapp_district" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(35) NOT NULL, "num" integer NOT NULL ) ; SELECT AddGeometryColumn('geoapp_school', 'point', 4326, 'POINT', 2); ALTER TABLE "geoapp_school" ALTER "point" SET NOT NULL; CREATE INDEX "geoapp_school_point_id" ON "geoapp_school" USING GIST ( "point" GIST_GEOMETRY_OPS ); SELECT AddGeometryColumn('geoapp_district', 'poly', 4326, 'POLYGON', 2); ALTER TABLE "geoapp_district" ALTER "poly" SET NOT NULL; CREATE INDEX "geoapp_district_poly_id" ON "geoapp_district" USING GIST ( "poly" GIST_GEOMETRY_OPS ); COMMIT;
$ python manage.py syncdb geoapp
Note: The geometry columns are created outside of the CREATE TABLE
statements by the AddGeometryColumn
. This is done according to the OpenGIS specfication.
- See Open GIS Consortium, Inc., OpenGIS Simple Feature Specification For SQL, Document 99-049 (May 5, 1999), at Ch. 2.3.8 (Geometry Values and Spatial Reference Systems, pg. 39).
Spatial Queries
After a geographic model has been created, the PostGIS additions to the API may be used. Geographic queries are done normally by using filter()
and exclude()
on geometry-enabled models using geographic lookup types (see the Database API for lookup types). In the following example, the bbcontains
lookup type is used which is the same as the PostGIS &&
operator. It looks to see if the bounding box of the polygon contains the specific point. The next example uses the PostGIS Contains()
function, which calls GEOS library to test if the polygon actually contains the specific point, not just the bounding box.
>>> from geoapp.models import District, School >>> qs1 = District.objects.filter(poly__bbcontains='POINT(-95.362293 29.756539)') >>> qs2 = District.objects.filter(poly__contains='POINT(-95.362293 29.756539)')
Both spatial queries and normal queries using filter()
may be used in the same query. For example, the following query set will only show school districts that have 'Houston' in their name and contain the given point within their polygon boundary:
>>> qs = District.objects.filter(name__contains='Houston').filter(poly__contains='POINT(-95.362293 29.756539)')
Or combine both the bounding box routines (less accurate, fast) with the GEOS routines (most accurate, slower) to get a query that is both fast and accurate:
>>> qs = District.objects.filter(poly__bbcontains='POINT(-95.362293 29.756539)').filter(poly__contains='POINT(-95.362293 29.756539)')
Lazy-Geometries
Geographic fields on models are proxies to GEOS Geometry objects, allowing for many interesting possibilities:
>>> from django.contrib.gis.geos import fromstr >>> pnt = fromstr('POINT(-95.362293 29.756539)', srid=4326) >>> hisd = District.objects.get(name='Houston ISD') >>> hisd.poly.contains(pnt) True >>> hisd.poly.within(pnt) False