mirror of
https://github.com/django/django.git
synced 2025-07-04 09:49:12 +00:00
gis: From jbronn:
Renamed LineString to LineStringField. Changed qs kwargs format, e.g. overlapsleft -> overlaps_left. Added oldforms WKTField, allowing read-only viewing of Geom fields (for people that know Well-Known Text). Index creation working for common case. git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@4851 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
8fe2413527
commit
177a49ae5e
@ -6,7 +6,7 @@ from django.contrib.gis.db.models.manager import GeoManager
|
|||||||
|
|
||||||
# The various PostGIS/OpenGIS enabled fields.
|
# The various PostGIS/OpenGIS enabled fields.
|
||||||
from django.contrib.gis.db.models.fields import \
|
from django.contrib.gis.db.models.fields import \
|
||||||
GeometryField, PointField, LineString, PolygonField, \
|
GeometryField, PointField, LineStringField, PolygonField, \
|
||||||
MultiPointField, MultiLineStringField, MultiPolygonField, \
|
MultiPointField, MultiLineStringField, MultiPolygonField, \
|
||||||
GeometryCollectionField
|
GeometryCollectionField
|
||||||
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
# The Django base Field class.
|
# The Django base Field class.
|
||||||
from django.db.models.fields import Field
|
from django.db.models.fields import Field
|
||||||
|
from django.oldforms import LargeTextField
|
||||||
from django.contrib.gis.db.models.postgis import POSTGIS_TERMS
|
from django.contrib.gis.db.models.postgis import POSTGIS_TERMS
|
||||||
|
from geos import geomToWKT, geomFromHEX
|
||||||
|
|
||||||
|
#TODO: add db.quotename.
|
||||||
|
|
||||||
# Creates the SQL to add the model to the database.
|
# Creates the SQL to add the model to the database.
|
||||||
def _add_geom(geom, srid, style, model, field, dim=2):
|
def _add_geom(geom, srid, style, model, field, dim=2):
|
||||||
@ -20,17 +24,26 @@ def _add_geom(geom, srid, style, model, field, dim=2):
|
|||||||
# Creates an index for the given geometry.
|
# Creates an index for the given geometry.
|
||||||
def _geom_index(geom, style, model, field,
|
def _geom_index(geom, style, model, field,
|
||||||
index_type='GIST',
|
index_type='GIST',
|
||||||
index_opts='GIST_GEOMETRY_OPTS'):
|
index_opts='GIST_GEOMETRY_OPS'):
|
||||||
sql = style.SQL_KEYWORD('CREATE INDEX ') + \
|
sql = style.SQL_KEYWORD('CREATE INDEX ') + \
|
||||||
style.SQL_FIELD(field + '_idx') + \
|
style.SQL_TABLE('"%s_%s_id"' % (model, field)) + \
|
||||||
style.SQL_KEYWORD(' ON ') + \
|
style.SQL_KEYWORD(' ON ') + \
|
||||||
style.SQL_TABLE(model) + \
|
style.SQL_TABLE('"%s"' % model) + \
|
||||||
style.SQL_KEYWORD(' USING ') + \
|
style.SQL_KEYWORD(' USING ') + \
|
||||||
style.SQL_COLTYPE(index_type) + ' ( ' + \
|
style.SQL_COLTYPE(index_type) + ' ( ' + \
|
||||||
style.SQL_FIELD(field) + ' ' + \
|
style.SQL_FIELD('"%s"' % field) + ' ' + \
|
||||||
style.SQL_KEYWORD(index_opts) + ' );'
|
style.SQL_KEYWORD(index_opts) + ' );'
|
||||||
return sql
|
return sql
|
||||||
|
|
||||||
|
class WKTField(LargeTextField):
|
||||||
|
"An oldforms LargeTextField for editing WKT text in the admin."
|
||||||
|
|
||||||
|
def render(self, data):
|
||||||
|
# PostGIS uses EWKBHEX to store its values internally, converting
|
||||||
|
# to WKT for the admin first.
|
||||||
|
wkt = geomToWKT(geomFromHEX(data))
|
||||||
|
return super(WKTField, self).render(wkt)
|
||||||
|
|
||||||
class GeometryField(Field):
|
class GeometryField(Field):
|
||||||
"The base GIS field -- maps to the OpenGIS Geometry type."
|
"The base GIS field -- maps to the OpenGIS Geometry type."
|
||||||
|
|
||||||
@ -38,12 +51,19 @@ class GeometryField(Field):
|
|||||||
_geom = 'GEOMETRY'
|
_geom = 'GEOMETRY'
|
||||||
|
|
||||||
def __init__(self, srid=4326, index=False, **kwargs):
|
def __init__(self, srid=4326, index=False, **kwargs):
|
||||||
|
#TODO: SRID a standard, or specific to postgis?
|
||||||
|
# Whether or not index this field, defaults to False
|
||||||
|
# Why can't we just use db_index?
|
||||||
|
# TODO: Move index creation (and kwarg lookup, and...)
|
||||||
|
# into Field rather than core.management and db.models.query.
|
||||||
|
self._index = index
|
||||||
|
|
||||||
|
# The SRID for the geometry, defaults to 4326.
|
||||||
|
self._srid = srid
|
||||||
|
|
||||||
# Calling the Field initialization function first
|
# Calling the Field initialization function first
|
||||||
super(GeometryField, self).__init__(**kwargs)
|
super(GeometryField, self).__init__(**kwargs)
|
||||||
|
|
||||||
# The SRID for the geometry, defaults to 4326
|
|
||||||
self._srid = srid
|
|
||||||
self._index = index
|
|
||||||
|
|
||||||
def get_internal_type(self):
|
def get_internal_type(self):
|
||||||
return "NoField"
|
return "NoField"
|
||||||
@ -51,11 +71,16 @@ class GeometryField(Field):
|
|||||||
def _post_create_sql(self, *args, **kwargs):
|
def _post_create_sql(self, *args, **kwargs):
|
||||||
"""Returns SQL that will be executed after the model has been created. Geometry
|
"""Returns SQL that will be executed after the model has been created. Geometry
|
||||||
columns must be added after creation with the PostGIS AddGeometryColumn() function."""
|
columns must be added after creation with the PostGIS AddGeometryColumn() function."""
|
||||||
|
|
||||||
|
#TODO: clean up *args/**kwargs.
|
||||||
|
|
||||||
|
# Getting the AddGeometryColumn() SQL necessary to create a PostGIS
|
||||||
|
# geometry field.
|
||||||
post_sql = _add_geom(self._geom, self._srid, *args, **kwargs)
|
post_sql = _add_geom(self._geom, self._srid, *args, **kwargs)
|
||||||
|
|
||||||
|
# If the user wants to index this data, then get the indexing SQL as well.
|
||||||
if self._index:
|
if self._index:
|
||||||
# Creating geometry indices doesn't yet work.
|
return '%s\n%s' % (post_sql, _geom_index(self._geom, *args, **kwargs))
|
||||||
#return '%s\n%s' % (post_sql, _geom_index(self._geom, *args, **kwargs))
|
|
||||||
return post_sql
|
|
||||||
else:
|
else:
|
||||||
return post_sql
|
return post_sql
|
||||||
|
|
||||||
@ -69,12 +94,16 @@ class GeometryField(Field):
|
|||||||
def get_db_prep_save(self, value):
|
def get_db_prep_save(self, value):
|
||||||
"Making sure the SRID is included before saving."
|
"Making sure the SRID is included before saving."
|
||||||
return 'SRID=%d;%s' % (self._srid, value)
|
return 'SRID=%d;%s' % (self._srid, value)
|
||||||
|
|
||||||
|
def get_manipulator_field_objs(self):
|
||||||
|
"Using the WKTField (defined above) to be our manipulator."
|
||||||
|
return [WKTField]
|
||||||
|
|
||||||
# The OpenGIS Geometry Type Fields
|
# The OpenGIS Geometry Type Fields
|
||||||
class PointField(GeometryField):
|
class PointField(GeometryField):
|
||||||
_geom = 'POINT'
|
_geom = 'POINT'
|
||||||
|
|
||||||
class LineString(GeometryField):
|
class LineStringField(GeometryField):
|
||||||
_geom = 'LINESTRING'
|
_geom = 'LINESTRING'
|
||||||
|
|
||||||
class PolygonField(GeometryField):
|
class PolygonField(GeometryField):
|
||||||
|
@ -2,33 +2,31 @@
|
|||||||
# django.db.models.query objects to be customized for PostGIS.
|
# django.db.models.query objects to be customized for PostGIS.
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from django.db import backend
|
from django.db import backend
|
||||||
from django.db.models.query import \
|
from django.db.models.query import LOOKUP_SEPARATOR, find_field, FieldFound
|
||||||
LOOKUP_SEPARATOR, QUERY_TERMS, \
|
|
||||||
find_field, FieldFound, get_where_clause
|
|
||||||
from django.utils.datastructures import SortedDict
|
from django.utils.datastructures import SortedDict
|
||||||
|
|
||||||
# PostGIS-specific operators. The commented descriptions of these
|
# PostGIS-specific operators. The commented descriptions of these
|
||||||
# operators come from Section 6.2.2 of the official PostGIS documentation.
|
# operators come from Section 6.2.2 of the official PostGIS documentation.
|
||||||
POSTGIS_OPERATORS = {
|
POSTGIS_OPERATORS = {
|
||||||
# The "&<" operator returns true if A's bounding box overlaps or is to the left of B's bounding box.
|
# The "&<" operator returns true if A's bounding box overlaps or is to the left of B's bounding box.
|
||||||
'overlapsleft' : '&< %s',
|
'overlaps_left' : '&< %s',
|
||||||
# The "&>" operator returns true if A's bounding box overlaps or is to the right of B's bounding box.
|
# The "&>" operator returns true if A's bounding box overlaps or is to the right of B's bounding box.
|
||||||
'overlapsright' : '&> %s',
|
'overlaps_right' : '&> %s',
|
||||||
# The "<<" operator returns true if A's bounding box is strictly to the left of B's bounding box.
|
# The "<<" operator returns true if A's bounding box is strictly to the left of B's bounding box.
|
||||||
'left' : '<< %s',
|
'left' : '<< %s',
|
||||||
# The ">>" operator returns true if A's bounding box is strictly to the right of B's bounding box.
|
# The ">>" operator returns true if A's bounding box is strictly to the right of B's bounding box.
|
||||||
'right' : '>> %s',
|
'right' : '>> %s',
|
||||||
# The "&<|" operator returns true if A's bounding box overlaps or is below B's bounding box.
|
# The "&<|" operator returns true if A's bounding box overlaps or is below B's bounding box.
|
||||||
'overlapsbelow' : '&<| %s',
|
'overlaps_below' : '&<| %s',
|
||||||
# The "|&>" operator returns true if A's bounding box overlaps or is above B's bounding box.
|
# The "|&>" operator returns true if A's bounding box overlaps or is above B's bounding box.
|
||||||
'overlapsabove' : '|&> %s',
|
'overlaps_above' : '|&> %s',
|
||||||
# The "<<|" operator returns true if A's bounding box is strictly below B's bounding box.
|
# The "<<|" operator returns true if A's bounding box is strictly below B's bounding box.
|
||||||
'strictlybelow' : '<<| %s',
|
'strictly_below' : '<<| %s',
|
||||||
# The "|>>" operator returns true if A's bounding box is strictly above B's bounding box.
|
# The "|>>" operator returns true if A's bounding box is strictly above B's bounding box.
|
||||||
'strictlyabove' : '|>> %s',
|
'strictly_above' : '|>> %s',
|
||||||
# The "~=" operator is the "same as" operator. It tests actual geometric equality of two features. So if
|
# The "~=" operator is the "same as" operator. It tests actual geometric equality of two features. So if
|
||||||
# A and B are the same feature, vertex-by-vertex, the operator returns true.
|
# A and B are the same feature, vertex-by-vertex, the operator returns true.
|
||||||
'sameas' : '~= %s',
|
'same_as' : '~= %s',
|
||||||
# The "@" operator returns true if A's bounding box is completely contained by B's bounding box.
|
# The "@" operator returns true if A's bounding box is completely contained by B's bounding box.
|
||||||
'contained' : '@ %s',
|
'contained' : '@ %s',
|
||||||
# The "~" operator returns true if A's bounding box completely contains B's bounding box.
|
# The "~" operator returns true if A's bounding box completely contains B's bounding box.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user