Fixed #23108 -- Dropped support for PostgreSQL 8.4 & PostGIS 1.3, 1.4.

Thanks Claude Paroz for the review.
This commit is contained in:
Tim Graham 2014-07-26 16:55:31 -04:00
parent 7ce4ef58c9
commit a9bdce7e55
18 changed files with 86 additions and 185 deletions

View File

@ -25,12 +25,13 @@ class PostGISIntrospection(DatabaseIntrospection):
identification integers for the PostGIS geometry and/or
geography types (if supported).
"""
field_types = [('geometry', 'GeometryField')]
if self.connection.ops.geography:
field_types = [
('geometry', 'GeometryField'),
# The value for the geography type is actually a tuple
# to pass in the `geography=True` keyword to the field
# definition.
field_types.append(('geography', ('GeometryField', {'geography': True})))
('geography', ('GeometryField', {'geography': True})),
]
postgis_types = {}
# The OID integers associated with the geometry type may
@ -79,12 +80,11 @@ class PostGISIntrospection(DatabaseIntrospection):
if not row:
raise GeoIntrospectionError
except GeoIntrospectionError:
if self.connection.ops.geography:
cursor.execute('SELECT "coord_dimension", "srid", "type" '
'FROM "geography_columns" '
'WHERE "f_table_name"=%s AND "f_geography_column"=%s',
(table_name, geo_col))
row = cursor.fetchone()
cursor.execute('SELECT "coord_dimension", "srid", "type" '
'FROM "geography_columns" '
'WHERE "f_table_name"=%s AND "f_geography_column"=%s',
(table_name, geo_col))
row = cursor.fetchone()
if not row:
raise Exception('Could not find a geometry or geography column for "%s"."%s"' %

View File

@ -74,6 +74,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
compiler_module = 'django.contrib.gis.db.models.sql.compiler'
name = 'postgis'
postgis = True
geography = True
geom_func_prefix = 'ST_'
version_regex = re.compile(r'^(?P<major>\d)\.(?P<minor1>\d)\.(?P<minor2>\d+)')
valid_aggregates = {'Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union'}
@ -140,6 +141,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
'relate': (PostGISRelate, six.string_types),
'coveredby': PostGISFunction(prefix, 'CoveredBy'),
'covers': PostGISFunction(prefix, 'Covers'),
'contains_properly': PostGISFunction(prefix, 'ContainsProperly'),
}
# Valid distance types and substitutions
@ -162,34 +164,17 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
# Adding the distance functions to the geometries lookup.
self.geometry_functions.update(self.distance_functions)
# Only PostGIS versions 1.3.4+ have GeoJSON serialization support.
if self.spatial_version < (1, 3, 4):
GEOJSON = False
else:
GEOJSON = prefix + 'AsGeoJson'
# ST_ContainsProperly ST_MakeLine, and ST_GeoHash added in 1.4.
if self.spatial_version >= (1, 4, 0):
GEOHASH = 'ST_GeoHash'
BOUNDINGCIRCLE = 'ST_MinimumBoundingCircle'
self.geometry_functions['contains_properly'] = PostGISFunction(prefix, 'ContainsProperly')
else:
GEOHASH, BOUNDINGCIRCLE = False, False
# Geography type support added in 1.5.
if self.spatial_version >= (1, 5, 0):
self.geography = True
# Only a subset of the operators and functions are available
# for the geography type.
self.geography_functions = self.distance_functions.copy()
self.geography_functions.update({
'coveredby': self.geometry_functions['coveredby'],
'covers': self.geometry_functions['covers'],
'intersects': self.geometry_functions['intersects'],
})
self.geography_operators = {
'bboverlaps': PostGISOperator('&&'),
}
# Only a subset of the operators and functions are available
# for the geography type.
self.geography_functions = self.distance_functions.copy()
self.geography_functions.update({
'coveredby': self.geometry_functions['coveredby'],
'covers': self.geometry_functions['covers'],
'intersects': self.geometry_functions['intersects'],
})
self.geography_operators = {
'bboverlaps': PostGISOperator('&&'),
}
# Native geometry type support added in PostGIS 2.0.
if self.spatial_version >= (2, 0, 0):
@ -201,7 +186,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
self.gis_terms.update(self.geometry_functions)
self.area = prefix + 'Area'
self.bounding_circle = BOUNDINGCIRCLE
self.bounding_circle = prefix + 'MinimumBoundingCircle'
self.centroid = prefix + 'Centroid'
self.collect = prefix + 'Collect'
self.difference = prefix + 'Difference'
@ -211,8 +196,8 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
self.envelope = prefix + 'Envelope'
self.extent = prefix + 'Extent'
self.force_rhr = prefix + 'ForceRHR'
self.geohash = GEOHASH
self.geojson = GEOJSON
self.geohash = prefix + 'GeoHash'
self.geojson = prefix + 'AsGeoJson'
self.gml = prefix + 'AsGML'
self.intersection = prefix + 'Intersection'
self.kml = prefix + 'AsKML'
@ -261,7 +246,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
except ProgrammingError:
raise ImproperlyConfigured(
'Cannot determine PostGIS version for database "%s". '
'GeoDjango requires at least PostGIS version 1.3. '
'GeoDjango requires at least PostGIS version 1.5. '
'Was the database created from a spatial database '
'template?' % self.connection.settings_dict['NAME']
)
@ -315,12 +300,8 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
has been specified to be of geography type instead.
"""
if f.geography:
if not self.geography:
raise NotImplementedError('PostGIS 1.5 required for geography column support.')
if f.srid != 4326:
raise NotImplementedError('PostGIS 1.5 supports geography columns '
'only with an SRID of 4326.')
raise NotImplementedError('PostGIS only supports geography columns with an SRID of 4326.')
return 'geography(%s,%d)' % (f.geom_type, f.srid)
elif self.geometry:
@ -352,7 +333,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
# Shorthand boolean flags.
geodetic = f.geodetic(self.connection)
geography = f.geography and self.geography
geography = f.geography
if isinstance(value, Distance):
if geography:
@ -525,15 +506,6 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
op = op(self.geom_func_prefix, value[1])
elif lookup_type in self.distance_functions and lookup_type != 'dwithin':
if not field.geography and field.geodetic(self.connection):
# Geodetic distances are only available from Points to
# PointFields on PostGIS 1.4 and below.
if not self.connection.ops.geography:
if field.geom_type != 'POINT':
raise ValueError('PostGIS spherical operations are only valid on PointFields.')
if str(geom.geom_type) != 'Point':
raise ValueError('PostGIS geometry distance parameter is required to be of type Point.')
# Setting up the geodetic operation appropriately.
if nparams == 3 and value[2] == 'spheroid':
op = op['spheroid']

View File

@ -151,24 +151,13 @@ class GeoQuerySet(QuerySet):
if not isinstance(precision, six.integer_types):
raise TypeError('Precision keyword must be set with an integer.')
# Setting the options flag -- which depends on which version of
# PostGIS we're using. SpatiaLite only uses the first group of options.
if backend.spatial_version >= (1, 4, 0):
options = 0
if crs and bbox:
options = 3
elif bbox:
options = 1
elif crs:
options = 2
else:
options = 0
if crs and bbox:
options = 3
elif crs:
options = 1
elif bbox:
options = 2
options = 0
if crs and bbox:
options = 3
elif bbox:
options = 1
elif crs:
options = 2
s = {'desc': 'GeoJSON',
'procedure_args': {'precision': precision, 'options': options},
'procedure_fmt': '%(geo_col)s,%(precision)s,%(options)s',
@ -197,12 +186,7 @@ class GeoQuerySet(QuerySet):
backend = connections[self.db].ops
s = {'desc': 'GML', 'procedure_args': {'precision': precision}}
if backend.postgis:
# PostGIS AsGML() aggregate function parameter order depends on the
# version -- uggh.
if backend.spatial_version > (1, 3, 1):
s['procedure_fmt'] = '%(version)s,%(geo_col)s,%(precision)s'
else:
s['procedure_fmt'] = '%(geo_col)s,%(precision)s,%(version)s'
s['procedure_fmt'] = '%(version)s,%(geo_col)s,%(precision)s'
s['procedure_args'] = {'precision': precision, 'version': version}
return self._spatial_attribute('gml', s, **kwargs)

View File

@ -147,7 +147,7 @@ class DistanceTest(TestCase):
# Testing geodetic distance calculation with a non-point geometry
# (a LineString of Wollongong and Shellharbour coords).
ls = LineString(((150.902, -34.4245), (150.87, -34.5789)))
if oracle or connection.ops.geography:
if oracle or postgis:
# Reference query:
# SELECT ST_distance_sphere(point, ST_GeomFromText('LINESTRING(150.9020 -34.4245,150.8700 -34.5789)', 4326)) FROM distapp_australiacity ORDER BY name;
distances = [1120954.92533513, 140575.720018241, 640396.662906304,
@ -157,11 +157,6 @@ class DistanceTest(TestCase):
for city, distance in zip(qs, distances):
# Testing equivalence to within a meter.
self.assertAlmostEqual(distance, city.distance.m, 0)
else:
# PostGIS 1.4 and below is limited to disance queries only
# to/from point geometries, check for raising of ValueError.
self.assertRaises(ValueError, AustraliaCity.objects.distance, ls)
self.assertRaises(ValueError, AustraliaCity.objects.distance, ls.wkt)
# Got the reference distances using the raw SQL statements:
# SELECT ST_distance_spheroid(point, ST_GeomFromText('POINT(151.231341 -33.952685)', 4326), 'SPHEROID["WGS 84",6378137.0,298.257223563]') FROM distapp_australiacity WHERE (NOT (id = 11));
@ -204,11 +199,6 @@ class DistanceTest(TestCase):
"""
Test the `distance` GeoQuerySet method used with `transform` on a geographic field.
"""
# Normally you can't compute distances from a geometry field
# that is not a PointField (on PostGIS 1.4 and below).
if not connection.ops.geography:
self.assertRaises(ValueError, CensusZipcode.objects.distance, self.stx_pnt)
# We'll be using a Polygon (created by buffering the centroid
# of 77005 to 100m) -- which aren't allowed in geographic distance
# queries normally, however our field has been transformed to
@ -272,15 +262,15 @@ class DistanceTest(TestCase):
line = GEOSGeometry('LINESTRING(144.9630 -37.8143,151.2607 -33.8870)', 4326)
dist_qs = AustraliaCity.objects.filter(point__distance_lte=(line, D(km=100)))
if oracle or connection.ops.geography:
# Oracle and PostGIS 1.5 can do distance lookups on arbitrary geometries.
if oracle or postgis:
# Oracle and PostGIS can do distance lookups on arbitrary geometries.
self.assertEqual(9, dist_qs.count())
self.assertEqual(['Batemans Bay', 'Canberra', 'Hillsdale',
'Melbourne', 'Mittagong', 'Shellharbour',
'Sydney', 'Thirroul', 'Wollongong'],
self.get_names(dist_qs))
else:
# PostGIS 1.4 and below only allows geodetic distance queries (utilizing
# spatialite only allow geodetic distance queries (utilizing
# ST_Distance_Sphere/ST_Distance_Spheroid) from Points to PointFields
# on geometry columns.
self.assertRaises(ValueError, dist_qs.count)

View File

@ -70,7 +70,7 @@ class Geo3DTest(TestCase):
available within GeoDjango. For more information, see the PostGIS docs
on the routines that support 3D:
http://postgis.refractions.net/documentation/manual-1.4/ch08.html#PostGIS_3D_Functions
http://postgis.refractions.net/documentation/manual-1.5/ch08.html#PostGIS_3D_Functions
"""
def _load_interstate_data(self):

View File

@ -507,11 +507,7 @@ class GeoQuerySetTest(TestCase):
houston_json = '{"type":"Point","crs":{"type":"name","properties":{"name":"EPSG:4326"}},"coordinates":[-95.363151,29.763374]}'
victoria_json = '{"type":"Point","bbox":[-123.30519600,48.46261100,-123.30519600,48.46261100],"coordinates":[-123.305196,48.462611]}'
chicago_json = '{"type":"Point","crs":{"type":"name","properties":{"name":"EPSG:4326"}},"bbox":[-87.65018,41.85039,-87.65018,41.85039],"coordinates":[-87.65018,41.85039]}'
if postgis and connection.ops.spatial_version < (1, 4, 0):
pueblo_json = '{"type":"Point","coordinates":[-104.60925200,38.25500100]}'
houston_json = '{"type":"Point","crs":{"type":"EPSG","properties":{"EPSG":4326}},"coordinates":[-95.36315100,29.76337400]}'
victoria_json = '{"type":"Point","bbox":[-123.30519600,48.46261100,-123.30519600,48.46261100],"coordinates":[-123.30519600,48.46261100]}'
elif spatialite:
if spatialite:
victoria_json = '{"type":"Point","bbox":[-123.305196,48.462611,-123.305196,48.462611],"coordinates":[-123.305196,48.462611]}'
# Precision argument should only be an integer
@ -560,10 +556,8 @@ class GeoQuerySetTest(TestCase):
for ptown in [ptown1, ptown2]:
self.assertTrue(gml_regex.match(ptown.gml))
# PostGIS < 1.5 doesn't include dimension im GMLv3 output.
if postgis and connection.ops.spatial_version >= (1, 5, 0):
self.assertIn('<gml:pos srsDimension="2">',
City.objects.gml(version=3).get(name='Pueblo').gml)
if postgis:
self.assertIn('<gml:pos srsDimension="2">', City.objects.gml(version=3).get(name='Pueblo').gml)
def test_kml(self):
"Testing KML output from the database using GeoQuerySet.kml()."
@ -577,18 +571,11 @@ class GeoQuerySetTest(TestCase):
qs = City.objects.all()
self.assertRaises(TypeError, qs.kml, 'name')
# The reference KML depends on the version of PostGIS used
# (the output stopped including altitude in 1.3.3).
if connection.ops.spatial_version >= (1, 3, 3):
ref_kml = '<Point><coordinates>-104.609252,38.255001</coordinates></Point>'
else:
ref_kml = '<Point><coordinates>-104.609252,38.255001,0</coordinates></Point>'
# Ensuring the KML is as expected.
ptown1 = City.objects.kml(field_name='point', precision=9).get(name='Pueblo')
ptown2 = City.objects.kml(precision=9).get(name='Pueblo')
for ptown in [ptown1, ptown2]:
self.assertEqual(ref_kml, ptown.kml)
self.assertEqual('<Point><coordinates>-104.609252,38.255001</coordinates></Point>', ptown.kml)
# Only PostGIS has support for the MakeLine aggregate.
@no_mysql

View File

@ -1,5 +1,5 @@
"""
Tests for geography support in PostGIS 1.5+
Tests for geography support in PostGIS
"""
from __future__ import unicode_literals

View File

@ -6,10 +6,10 @@ import re
# This reg-exp is intentionally fairly flexible here.
# Needs to be able to handle stuff like:
# PostgreSQL 8.3.6
# EnterpriseDB 8.3
# PostgreSQL 8.3 beta4
# PostgreSQL 8.4beta1
# PostgreSQL #.#.#
# EnterpriseDB #.#
# PostgreSQL #.# beta#
# PostgreSQL #.#beta#
VERSION_RE = re.compile(r'\S+ (\d+)\.(\d+)\.?(\d+)?')
@ -29,8 +29,8 @@ def get_version(connection):
PQServerVersion()/``server_version`` connection attribute (available in
newer psycopg2 versions.)
For example, 80304 for 8.3.4. The last two digits will be 00 in the case of
releases (e.g., 80400 for 'PostgreSQL 8.4') or in the case of beta and
For example, 90304 for 9.3.4. The last two digits will be 00 in the case of
releases (e.g., 90400 for 'PostgreSQL 9.4') or in the case of beta and
prereleases (e.g. 90100 for 'PostgreSQL 9.1beta2').
PQServerVersion()/``server_version`` doesn't execute a query so try that

View File

@ -1,9 +0,0 @@
#!/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

@ -1,9 +0,0 @@
#!/usr/bin/env bash
POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib
createdb -E UTF8 template_postgis # Create the template spatial database.
createlang -d template_postgis plpgsql # Adding PLPGSQL language support.
psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';"
psql -d template_postgis -f $POSTGIS_SQL_PATH/postgis.sql # Loading the PostGIS SQL routines
psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql
psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" # Enabling users to alter spatial tables.
psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"

View File

@ -1,26 +1,11 @@
#!/bin/bash
GEOGRAPHY=0
POSTGIS_SQL=postgis.sql
# For Ubuntu 10.04
if [ -d "/usr/share/postgresql/8.4/contrib" ]
then
POSTGIS_SQL_PATH=/usr/share/postgresql/8.4/contrib
fi
# For Ubuntu 10.10 (with PostGIS 1.5)
if [ -d "/usr/share/postgresql/8.4/contrib/postgis-1.5" ]
then
POSTGIS_SQL_PATH=/usr/share/postgresql/8.4/contrib/postgis-1.5
GEOGRAPHY=1
fi
# For Ubuntu 11.10 / Linux Mint 12 (with PostGIS 1.5)
# For Ubuntu 11.10, 12.04 / Linux Mint 12 (with PostGIS 1.5)
if [ -d "/usr/share/postgresql/9.1/contrib/postgis-1.5" ]
then
POSTGIS_SQL_PATH=/usr/share/postgresql/9.1/contrib/postgis-1.5
GEOGRAPHY=1
fi
createdb -E UTF8 template_postgis && \
@ -30,8 +15,4 @@ psql -d template_postgis -f $POSTGIS_SQL_PATH/$POSTGIS_SQL && \
psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql && \
psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;" && \
psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"
if [ $GEOGRAPHY -eq 1 ]
then
psql -d template_postgis -c "GRANT ALL ON geography_columns TO PUBLIC;"
fi
psql -d template_postgis -c "GRANT ALL ON geography_columns TO PUBLIC;"

View File

@ -14,7 +14,7 @@ Program Description Required
`PROJ.4`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 4.8, 4.7, 4.6, 4.5, 4.4
:ref:`GDAL <ref-gdal>` Geospatial Data Abstraction Library Yes (SQLite only) 1.10, 1.9, 1.8, 1.7
:ref:`GeoIP <ref-geoip>` IP-based geolocation library No 1.4
`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 2.1, 2.0, 1.5, 1.4, 1.3
`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 2.1, 2.0, 1.5
`SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 4.1, 4.0, 3.0, 2.4
======================== ==================================== ================================ ==========================
@ -31,8 +31,6 @@ totally fine with GeoDjango. Your mileage may vary.
GDAL 1.9.0 2012-01-03
GDAL 1.10.0 2013-04-29
GDAL 1.11.0 2014-04-25 # To be tested!
PostGIS 1.3.0 2007-08-09
PostGIS 1.4.0 2009-07-24
PostGIS 1.5.0 2010-02-04
PostGIS 2.0.0 2012-04-03
PostGIS 2.1.0 2013-08-17

View File

@ -61,7 +61,7 @@ supported versions, and any notes for each of the supported database backends:
================== ============================== ================== =========================================
Database Library Requirements Supported Versions Notes
================== ============================== ================== =========================================
PostgreSQL GEOS, PROJ.4, PostGIS 8.4+ Requires PostGIS.
PostgreSQL GEOS, PROJ.4, PostGIS 9.0+ Requires PostGIS.
MySQL GEOS 5.x Not OGC-compliant; :ref:`limited functionality <mysql-spatial-limitations>`.
Oracle GEOS 10.2, 11 XE not supported; not tested with 9.
SQLite GEOS, GDAL, PROJ.4, SpatiaLite 3.6.+ Requires SpatiaLite 2.3+, pysqlite2 2.5+
@ -107,8 +107,7 @@ Add Google projection to ``spatial_ref_sys`` table
.. note::
If you're running PostGIS 1.4 or above, you can skip this step. The entry
is already included in the default ``spatial_ref_sys`` table.
If you're running GDAL 1.7 or above (most users), you can skip this step.
In order to conduct database transformations to the so-called "Google"
projection (a spherical mercator projection used by Google Maps),
@ -361,7 +360,7 @@ the `Apple Developer Tools`_ are required.
Summary::
$ sudo port install postgresql83-server
$ sudo port install postgresql93-server
$ sudo port install geos
$ sudo port install proj
$ sudo port install postgis
@ -373,12 +372,12 @@ Summary::
You will also have to modify the ``PATH`` in your ``.profile`` so
that the MacPorts programs are accessible from the command-line::
export PATH=/opt/local/bin:/opt/local/lib/postgresql83/bin
export PATH=/opt/local/bin:/opt/local/lib/postgresql93/bin
In addition, add the ``DYLD_FALLBACK_LIBRARY_PATH`` setting so that
the libraries can be found by Python::
export DYLD_FALLBACK_LIBRARY_PATH=/opt/local/lib:/opt/local/lib/postgresql83
export DYLD_FALLBACK_LIBRARY_PATH=/opt/local/lib:/opt/local/lib/postgresql93
__ http://www.macports.org/

View File

@ -93,9 +93,7 @@ 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
``POSTGIS_SQL_PATH`` below) depends on the version of PostGIS.
PostGIS versions 1.3 and below use ``<pg_sharedir>/contrib/lwpostgis.sql``;
whereas version 1.4 uses ``<sharedir>/contrib/postgis.sql`` and
version 1.5 uses ``<sharedir>/contrib/postgis-1.5/postgis.sql``.
Version 1.5 uses ``<sharedir>/contrib/postgis-1.5/postgis.sql``.
To complicate matters, Debian/Ubuntu distributions have their own separate
directory naming system that might change with time. In this case, use the
@ -128,8 +126,6 @@ the following scripts are available:
=============== =============================================
PostGIS version Bash shell script
=============== =============================================
1.3 :download:`create_template_postgis-1.3.sh`
1.4 :download:`create_template_postgis-1.4.sh`
1.5 :download:`create_template_postgis-1.5.sh`
Debian/Ubuntu :download:`create_template_postgis-debian.sh`
=============== =============================================

View File

@ -784,13 +784,15 @@ available with the :class:`~django.contrib.gis.admin.GeoModelAdmin`
First, there are some important requirements:
* :class:`~django.contrib.gis.admin.OSMGeoAdmin` requires that the
:ref:`spherical mercator projection be added <addgoogleprojection>`
to the ``spatial_ref_sys`` table (PostGIS 1.3 and below, only).
* :class:`~django.contrib.gis.admin.OSMGeoAdmin` requires that
:ref:`GDAL <ref-gdal>` is installed. If you are running GDAL 1.6 (uncommon)
you will also need to add the :ref:`spherical mercator projection
<addgoogleprojection>` to the ``spatial_ref_sys`` table.
* 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 the ``OSMGeoAdmin``
If you meet this requirement, then just substitute the ``OSMGeoAdmin``
option class in your ``admin.py`` file::
admin.site.register(WorldBorder, admin.OSMGeoAdmin)

View File

@ -92,7 +92,7 @@ below for information on how to set up your database correctly.
PostgreSQL notes
================
Django supports PostgreSQL 8.4 and higher.
Django supports PostgreSQL 9.0 and higher.
PostgreSQL connection settings
-------------------------------

View File

@ -397,6 +397,16 @@ affected models (or add ``max_length=75`` if you wish to keep the length on
your current fields). A migration for
:attr:`django.contrib.auth.models.User.email` is included.
Support for PostgreSQL versions older than 9.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The end of upstream support periods was reached in July 2014 for PostgreSQL 8.4.
As a consequence, Django 1.8 sets 9.0 as the minimum PostgreSQL version it
officially supports.
This also includes dropping support for PostGIS 1.3 and 1.4 as these versions
are not supported on versions of PostgreSQL later than 8.4.
Miscellaneous
~~~~~~~~~~~~~

View File

@ -152,12 +152,12 @@ class PostgreSQLTests(TestCase):
def test_parsing(self):
"""Test PostgreSQL version parsing from `SELECT version()` output"""
self.assert_parses("PostgreSQL 8.3 beta4", 80300)
self.assert_parses("PostgreSQL 8.3", 80300)
self.assert_parses("EnterpriseDB 8.3", 80300)
self.assert_parses("PostgreSQL 8.3.6", 80306)
self.assert_parses("PostgreSQL 8.4beta1", 80400)
self.assert_parses("PostgreSQL 8.3.1 on i386-apple-darwin9.2.2, compiled by GCC i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5478)", 80301)
self.assert_parses("PostgreSQL 9.3 beta4", 90300)
self.assert_parses("PostgreSQL 9.3", 90300)
self.assert_parses("EnterpriseDB 9.3", 90300)
self.assert_parses("PostgreSQL 9.3.6", 90306)
self.assert_parses("PostgreSQL 9.4beta1", 90400)
self.assert_parses("PostgreSQL 9.3.1 on i386-apple-darwin9.2.2, compiled by GCC i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5478)", 90301)
def test_version_detection(self):
"""Test PostgreSQL version detection"""
@ -169,7 +169,7 @@ class PostgreSQLTests(TestCase):
pass
def fetchone(self):
return ["PostgreSQL 8.3"]
return ["PostgreSQL 9.3"]
def __enter__(self):
return self
@ -184,7 +184,7 @@ class PostgreSQLTests(TestCase):
# psycopg2 < 2.0.12 code path
conn = OlderConnectionMock()
self.assertEqual(pg_version.get_version(conn), 80300)
self.assertEqual(pg_version.get_version(conn), 90300)
def test_connect_and_rollback(self):
"""