Fixed #13315, #13430 -- Recreated `django.contrib.gis.db.backend` module with `SpatialBackend` alias and added `Adaptor` alias for backwards-compatibility purposes; added GeoDjango 1.2 backwards-incompatibility documentation and release notes; added a section in the docs about how MySQL is a crippled spatial database; updated versions in install docs.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@13097 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2010-05-04 21:43:40 +00:00
parent 41ccfa15d7
commit 402f8cede5
12 changed files with 226 additions and 26 deletions

View File

@ -0,0 +1,24 @@
from django.db import connection
if hasattr(connection.ops, 'spatial_version'):
from warnings import warn
warn('The `django.contrib.gis.db.backend` module was refactored and '
'renamed to `django.contrib.gis.db.backends` in 1.2. '
'All functionality of `SpatialBackend` '
'has been moved to the `ops` attribute of the spatial database '
'backend. A `SpatialBackend` alias is provided here for '
'backwards-compatibility, but will be removed in 1.3.')
SpatialBackend = connection.ops
from django.db import connection
if hasattr(connection.ops, 'spatial_version'):
from warnings import warn
warn('The `django.contrib.gis.db.backend` module was refactored and '
'renamed to `django.contrib.gis.db.backends` in 1.2. '
'All functionality of `SpatialBackend` '
'has been moved to the `ops` attribute of the spatial database '
'backend. A `SpatialBackend` alias is provided here for '
'backwards-compatibility, but will be removed in 1.3.')
SpatialBackend = connection.ops

View File

@ -13,6 +13,7 @@ class MySQLOperations(DatabaseOperations, BaseSpatialOperations):
from_text = 'GeomFromText' from_text = 'GeomFromText'
Adapter = WKTAdapter Adapter = WKTAdapter
Adaptor = Adapter # Backwards-compatibility alias.
geometry_functions = { geometry_functions = {
'bbcontains' : 'MBRContains', # For consistency w/PostGIS API 'bbcontains' : 'MBRContains', # For consistency w/PostGIS API

View File

@ -18,7 +18,6 @@ class GeometryColumns(models.Model):
srid = models.IntegerField(primary_key=True) srid = models.IntegerField(primary_key=True)
# TODO: Add support for `diminfo` column (type MDSYS.SDO_DIM_ARRAY). # TODO: Add support for `diminfo` column (type MDSYS.SDO_DIM_ARRAY).
class Meta: class Meta:
app_label = 'gis'
db_table = 'USER_SDO_GEOM_METADATA' db_table = 'USER_SDO_GEOM_METADATA'
managed = False managed = False
@ -54,7 +53,6 @@ class SpatialRefSys(models.Model, SpatialRefSysMixin):
objects = models.GeoManager() objects = models.GeoManager()
class Meta: class Meta:
app_label = 'gis'
db_table = 'CS_SRS' db_table = 'CS_SRS'
managed = False managed = False

View File

@ -75,6 +75,7 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
valid_aggregates = dict([(a, None) for a in ('Union', 'Extent')]) valid_aggregates = dict([(a, None) for a in ('Union', 'Extent')])
Adapter = OracleSpatialAdapter Adapter = OracleSpatialAdapter
Adaptor = Adapter # Backwards-compatibility alias.
area = 'SDO_GEOM.SDO_AREA' area = 'SDO_GEOM.SDO_AREA'
gml= 'SDO_UTIL.TO_GMLGEOMETRY' gml= 'SDO_UTIL.TO_GMLGEOMETRY'

View File

@ -18,7 +18,6 @@ class GeometryColumns(models.Model):
type = models.CharField(max_length=30) type = models.CharField(max_length=30)
class Meta: class Meta:
app_label = 'gis'
db_table = 'geometry_columns' db_table = 'geometry_columns'
managed = False managed = False
@ -55,7 +54,6 @@ class SpatialRefSys(models.Model, SpatialRefSysMixin):
proj4text = models.CharField(max_length=2048) proj4text = models.CharField(max_length=2048)
class Meta: class Meta:
app_label = 'gis'
db_table = 'spatial_ref_sys' db_table = 'spatial_ref_sys'
managed = False managed = False

View File

@ -66,6 +66,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
('Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union')]) ('Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union')])
Adapter = PostGISAdapter Adapter = PostGISAdapter
Adaptor = Adapter # Backwards-compatibility alias.
def __init__(self, connection): def __init__(self, connection):
super(PostGISOperations, self).__init__(connection) super(PostGISOperations, self).__init__(connection)

View File

@ -16,7 +16,6 @@ class GeometryColumns(models.Model):
spatial_index_enabled = models.IntegerField() spatial_index_enabled = models.IntegerField()
class Meta: class Meta:
app_label = 'gis'
db_table = 'geometry_columns' db_table = 'geometry_columns'
managed = False managed = False
@ -57,6 +56,5 @@ class SpatialRefSys(models.Model, SpatialRefSysMixin):
return SpatialReference(self.proj4text).wkt return SpatialReference(self.proj4text).wkt
class Meta: class Meta:
app_label = 'gis'
db_table = 'spatial_ref_sys' db_table = 'spatial_ref_sys'
managed = False managed = False

View File

@ -55,6 +55,7 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
valid_aggregates = dict([(k, None) for k in ('Extent', 'Union')]) valid_aggregates = dict([(k, None) for k in ('Extent', 'Union')])
Adapter = SpatiaLiteAdapter Adapter = SpatiaLiteAdapter
Adaptor = Adapter # Backwards-compatibility alias.
area = 'Area' area = 'Area'
centroid = 'Centroid' centroid = 'Centroid'

View File

@ -0,0 +1,9 @@
from django.db import connection
if (hasattr(connection.ops, 'spatial_version') and
not connection.ops.mysql):
# Getting the `SpatialRefSys` and `GeometryColumns`
# models for the default spatial backend. These
# aliases are provided for backwards-compatibility.
SpatialRefSys = connection.ops.spatial_ref_sys()
GeometryColumns = connection.ops.geometry_columns()

View File

@ -23,13 +23,16 @@ its functionality into full-fledged spatial database backends:
* :mod:`django.contrib.gis.db.backends.oracle` * :mod:`django.contrib.gis.db.backends.oracle`
* :mod:`django.contrib.gis.db.backends.spatialite` * :mod:`django.contrib.gis.db.backends.spatialite`
Backwards-Compatibility Database Settings Backwards-Compatibility
----------------------- -----------------------------------------
For those using the old database settings (e.g., the ``DATABASE_*`` settings) In :ref:`Django 1.2 <releases-1.2>`, the way
Django 1.2 will automatically use the appropriate spatial backend as long to :ref:`specify databases <specifying-databases>` in your settings was changed.
as :mod:`django.contrib.gis` is in your :setting:`INSTALLED_APPS`. For The old database settings format (e.g., the ``DATABASE_*`` settings)
example, if you have the following in your settings:: is backwards compatible with GeoDjango, and 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' DATABASE_ENGINE='postgresql_psycopg2'
@ -41,9 +44,37 @@ example, if you have the following in your settings::
... ...
) )
Then, :mod:`django.contrib.gis.db.backends.postgis` will automatically be used as your Then, :mod:`django.contrib.gis.db.backends.postgis` is automatically used as your
spatial backend. spatial backend.
.. _mysql-spatial-limitations:
MySQL Spatial Limitations
-------------------------
MySQL's spatial extensions only support bounding box operations
(what MySQL calls minimum bounding rectangles, or MBR). Specifically,
`MySQL does not conform to the OGC standard <http://dev.mysql.com/doc/refman/5.1/en/functions-that-test-spatial-relationships-between-geometries.html>`_:
Currently, MySQL does not implement these functions
[``Contains``, ``Crosses``, ``Disjoint``, ``Intersects``, ``Overlaps``,
``Touches``, ``Within``]
according to the specification. Those that are implemented return
the same result as the corresponding MBR-based functions.
In other words, while spatial lookups such as :lookup:`contains <gis-contains>`
are available in GeoDjango when using MySQL, the results returned are really
equivalent to what would be returned when using :lookup:`bbcontains`
on a different spatial backend.
.. warning::
True spatial indexes (R-trees) are only supported with
MyISAM tables on MySQL. [#fnmysqlidx]_ In other words, when using
MySQL spatial extensions you have to choose between fast spatial
lookups and the integrity of your data -- MyISAM tables do
not support transactions or foreign key constraints.
Creating and Saving Geographic Models Creating and Saving Geographic Models
===================================== =====================================
Here is an example of how to create a geometry object (assuming the ``Zipcode`` Here is an example of how to create a geometry object (assuming the ``Zipcode``
@ -307,4 +338,12 @@ Method PostGIS Oracle SpatiaLite
.. [#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). .. [#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).
.. [#fndistsphere14] *See* `PostGIS 1.4 documentation <http://postgis.refractions.net/documentation/manual-1.4/ST_Distance_Sphere.html>`_ on ``ST_distance_sphere``. .. [#fndistsphere14] *See* `PostGIS 1.4 documentation <http://postgis.refractions.net/documentation/manual-1.4/ST_Distance_Sphere.html>`_ on ``ST_distance_sphere``.
.. [#fndistsphere15] *See* `PostGIS 1.5 documentation <http://postgis.refractions.net/documentation/manual-1.5/ST_Distance_Sphere.html>`_ on ``ST_distance_sphere``. .. [#fndistsphere15] *See* `PostGIS 1.5 documentation <http://postgis.refractions.net/documentation/manual-1.5/ST_Distance_Sphere.html>`_ on ``ST_distance_sphere``.
.. [#] 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`. .. [#fnmysqlidx] *See* `Creating Spatial Indexes <http://dev.mysql.com/doc/refman/5.1/en/creating-spatial-indexes.html>`_
in the MySQL 5.1 Reference Manual:
For MyISAM tables, ``SPATIAL INDEX`` creates an R-tree index. For storage
engines that support nonspatial indexing of spatial columns, the engine
creates a B-tree index. A B-tree index on spatial values will be useful
for exact-value lookups, but not for range scans.
.. [#] Refer :ref:`mysql-spatial-limitations` section for more details.

View File

@ -150,13 +150,13 @@ directly from Python using ctypes.
First, download GEOS 3.2 from the refractions website and untar the source First, download GEOS 3.2 from the refractions website and untar the source
archive:: archive::
$ wget http://download.osgeo.org/geos/geos-3.2.1.tar.bz2 $ wget http://download.osgeo.org/geos/geos-3.2.2.tar.bz2
$ tar xjf geos-3.2.1.tar.bz2 $ tar xjf geos-3.2.2.tar.bz2
Next, change into the directory where GEOS was unpacked, run the configure Next, change into the directory where GEOS was unpacked, run the configure
script, compile, and install:: script, compile, and install::
$ cd geos-3.2.1 $ cd geos-3.2.2
$ ./configure $ ./configure
$ make $ make
$ sudo make install $ sudo make install
@ -273,9 +273,9 @@ supports :ref:`GDAL's vector data <ref-gdal>` capabilities [#]_.
First download the latest GDAL release version and untar the archive:: First download the latest GDAL release version and untar the archive::
$ wget http://download.osgeo.org/gdal/gdal-1.7.1.tar.gz $ wget http://download.osgeo.org/gdal/gdal-1.7.2.tar.gz
$ tar xzf gdal-1.7.1.tar.gz $ tar xzf gdal-1.7.2.tar.gz
$ cd gdal-1.7.1 $ cd gdal-1.7.2
Configure, make and install:: Configure, make and install::
@ -516,9 +516,9 @@ user. For example, you can use the following to become the ``postgres`` user::
The location *and* name of the PostGIS SQL files (e.g., from The location *and* name of the PostGIS SQL files (e.g., from
``POSTGIS_SQL_PATH`` below) depends on the version of PostGIS. ``POSTGIS_SQL_PATH`` below) depends on the version of PostGIS.
PostGIS versions 1.3 and below use ``<sharedir>/contrib/lwpostgis.sql``, whereas PostGIS versions 1.3 and below use ``<pg_sharedir>/contrib/lwpostgis.sql``;
versions 1.4 and 1.5 use ``<sharedir>/contrib/postgis-1.4/postgis.sql`` and whereas version 1.4 uses ``<sharedir>/contrib/postgis.sql`` and
``<sharedir>/contrib/postgis-1.5/postgis.sql``, respectively. version 1.5 uses ``<sharedir>/contrib/postgis-1.5/postgis.sql``.
The example below assumes PostGIS 1.5, thus you may need to modify The example below assumes PostGIS 1.5, thus you may need to modify
``POSTGIS_SQL_PATH`` and the name of the SQL file for the specific ``POSTGIS_SQL_PATH`` and the name of the SQL file for the specific

View File

@ -77,6 +77,9 @@ changes:
__members__ = property(lambda self: self.__dir__()) __members__ = property(lambda self: self.__dir__())
.. _specifying-databases:
Specifying databases Specifying databases
-------------------- --------------------
@ -338,8 +341,6 @@ you need an unmodified instance of your model, you should pass a copy to the
``ModelForm`` constructor. ``ModelForm`` constructor.
.. _deprecated-features-1.2:
``BooleanField`` on MySQL ``BooleanField`` on MySQL
-------------------------- --------------------------
@ -350,6 +351,8 @@ people this shouldn't have been a problem because ``bool`` is a subclass of
only time this should ever be an issue is if you were expecting printing the only time this should ever be an issue is if you were expecting printing the
``repr`` of a ``BooleanField`` to print ``1`` or ``0``. ``repr`` of a ``BooleanField`` to print ``1`` or ``0``.
.. _deprecated-features-1.2:
Features deprecated in 1.2 Features deprecated in 1.2
========================== ==========================
@ -363,7 +366,7 @@ library, has been deprecated.
If you are currently using the ``postgresql`` backend, you should If you are currently using the ``postgresql`` backend, you should
migrate to using the ``postgresql_psycopg2`` backend. To update your migrate to using the ``postgresql_psycopg2`` backend. To update your
code, install the ``psycopg2`` library and change the code, install the ``psycopg2`` library and change the
``DATABASE_ENGINE`` setting to read ``postgresql_psycopg2``. :setting:`DATABASE_ENGINE` setting to read ``postgresql_psycopg2``.
CSRF response-rewriting middleware CSRF response-rewriting middleware
---------------------------------- ----------------------------------
@ -594,6 +597,88 @@ deprecated in favor of the new :ref:`Format localization
information in a ``formats.py`` file in the corresponding information in a ``formats.py`` file in the corresponding
``django/conf/locale/<locale name>/`` directory. ``django/conf/locale/<locale name>/`` directory.
GeoDjango
---------
To allow support for multiple databases, the GeoDjango database internals were
changed substantially. The largest backwards-incompatible change is that
the module ``django.contrib.gis.db.backend`` was renamed to
:mod:`django.contrib.gis.db.backends`, where the full-fledged
:ref:`spatial databased backends <spatial-backends>` now exist. The
following sections provide information on the most-popular APIs that
were affected by these changes.
``SpatialBackend``
^^^^^^^^^^^^^^^^^^
Prior to the creation of the separate spatial backends, the
``django.contrib.gis.db.backend.SpatialBackend`` object was
provided as an abstraction to introspect on the capabilities of
the spatial database. All of the attributes and routines provided by
``SpatialBackend`` are now a part of the ``ops`` attribute of the
database backend.
The old module ``django.contrib.gis.db.backend`` is still provided
for backwards-compatibility access to a ``SpatialBackend`` object,
which is just an alias to the ``ops`` module of the
*default* spatial database connection.
Users that were relying on undocumented modules and objects
within ``django.contrib.gis.db.backend``, rather the abstractions
provided by ``SpatialBackend``, are required to modify their code.
For example, the following import which would work in 1.1 and
below::
from django.contrib.gis.db.backend.postgis import PostGISAdaptor
Would need to be changed::
from django.db import connection
PostGISAdaptor = connection.ops.Adapter
``SpatialRefSys`` and ``GeometryColumns`` models
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In previous versions of GeoDjango, :mod:`django.contrib.gis.db.models`
had ``SpatialRefSys`` and ``GeometryColumns`` models for querying
the OGC spatial metadata tables ``spatial_ref_sys`` and ``geometry_columns``,
respectively.
While these aliases are still provided, they are only for the
*default* database connection and exist only if the default connection
is using a supported spatial database backend.
.. note::
Because the table structure of the OGC spatial metadata tables
differs across spatial databases, the ``SpatialRefSys`` and
``GeometryColumns`` models can no longer be associated with
the ``gis`` application name. Thus, no models will be returned
when using the ``get_models`` method in the following example::
>>> from django.db.models import get_app, get_models
>>> get_models(get_app('gis'))
[]
To get the correct ``SpatialRefSys`` and ``GeometryColumns``
for your spatial database use the methods provided by the spatial backend::
>>> from django.db import connections
>>> SpatialRefSys = connections['my_spatialite'].ops.spatial_ref_sys()
>>> GeometryColumns = connections['my_postgis'].ops.geometry_columns()
.. note::
When using the models returned from the ``spatial_ref_sys()`` and
``geometry_columns()`` method, you'll still need to use the
correct database alias when querying on the non-default connection.
In other words, to ensure that the models in the example above
use the correct database::
sr_qs = SpatialRefSys.objects.using('my_spatialite').filter(...)
gc_qs = GeometryColumns.objects.using('my_postgis').filter(...)
What's new in Django 1.2 What's new in Django 1.2
======================== ========================
@ -793,6 +878,51 @@ The built-in :class:`~django.contrib.auth.models.User` model's
:attr:`~django.contrib.auth.models.User.username` field now allows a wider range :attr:`~django.contrib.auth.models.User.username` field now allows a wider range
of characters, including ``@``, ``+``, ``.`` and ``-`` characters. of characters, including ``@``, ``+``, ``.`` and ``-`` characters.
GeoDjango
---------
In 1.2, :ref:`GeoDjango <ref-contrib-gis>` was upgraded to provide
support for multiple spatial databases. As a result, the following
:ref:`spatial database backends <spatial-backends>`
are now included:
* :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`
GeoDjango now supports the rich capabilities added
in the `PostGIS 1.5 release <http://postgis.refractions.net/documentation/manual-1.5/>`_.
New features include suppport for the the :ref:`geography type <geography-type>`
and enabling of :ref:`distance queries <distance-queries>`
with non-point geometries on geographic coordinate systems.
Support for 3D geometry fields was added, and may be enabled
by setting the :attr:`~django.contrib.gis.db.models.GeometryField.dim`
keyword to 3 in your :class:`~django.contrib.gis.db.models.GeometryField`.
The :class:`~django.contrib.gis.db.models.Extent3D` aggregate
and :meth:`~django.contrib.gis.db.models.GeoQuerySet.extent3d` ``GeoQuerySet``
method were added as a part of this feature.
The following :class:`~django.contrib.gis.db.models.GeoQeurySet`
methods are new in 1.2:
* :meth:`~django.contrib.gis.db.models.GeoQuerySet.force_rhr`
* :meth:`~django.contrib.gis.db.models.GeoQuerySet.reverse_geom`
* :meth:`~django.contrib.gis.db.models.GeoQuerySet.geohash`
The :ref:`GEOS interface <ref-geos>` was updated to use
thread-safe C library functions when available on the platform.
The :ref:`GDAL interface <ref-gdal>` now allows the user to place
set a :attr:`~django.contrib.gis.gdal.Layer.spatial_filter` on
the features returned from a :class:`~django.contrib.gis.gdal.DataSource`
:class:`~django.contrib.gis.gdal.Layer`.
Finally, :ref:`GeoDjango's documentation <ref-contrib-gis>` is now
included with Django's and is no longer
hosted separately at `geodjango.org <http://geodjango.org/>`_.
Deprecation of old language code ``no`` Deprecation of old language code ``no``
--------------------------------------- ---------------------------------------