summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Dunck <jdunck@gmail.com>2007-03-07 23:09:33 +0000
committerJeremy Dunck <jdunck@gmail.com>2007-03-07 23:09:33 +0000
commit5edcbdc826b4d87cdb9ba28b4467b3806bdcdb52 (patch)
treeb69f9e2dcd213bb91845c2829f7576c1a7ce9785
parent5514d8731955466dad0cdaf395ddd4da1c101274 (diff)
gis: Added beginnings of django.contrib.gis.
Changed ManyToManyField to provide get_internal_type() -> 'NoField'. GIS fields use NoField? and new _post_create_sql for AddGeometryColumn. git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@4674 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/contrib/gis/__init__.py71
-rw-r--r--django/contrib/gis/db/__init__.py0
-rw-r--r--django/contrib/gis/db/models/__init__.py0
-rw-r--r--django/contrib/gis/db/models/fields/__init__.py72
-rw-r--r--django/core/management.py4
-rw-r--r--django/db/backends/ado_mssql/creation.py2
-rw-r--r--django/db/backends/mysql/creation.py2
-rw-r--r--django/db/backends/oracle/creation.py2
-rw-r--r--django/db/backends/postgresql/creation.py2
-rw-r--r--django/db/backends/sqlite3/creation.py2
-rw-r--r--django/db/models/fields/related.py3
11 files changed, 155 insertions, 5 deletions
diff --git a/django/contrib/gis/__init__.py b/django/contrib/gis/__init__.py
new file mode 100644
index 0000000000..2266ce4b95
--- /dev/null
+++ b/django/contrib/gis/__init__.py
@@ -0,0 +1,71 @@
+from geos import geomFromWKT, geomToWKT
+from decimal import Decimal
+from django.db import models
+from django.db.models.query import QuerySet
+
+
+class GeoQuerySet(QuerySet):
+ # The list of valid query terms
+ # override the local QUERY_TERMS in the namespace
+ # not sure how to do that locals() hackery
+ # possibly in the init change its locals() variables
+ # not sure if that will work
+
+ QUERY_TERMS = (
+ 'exact', 'iexact', 'contains', 'icontains', 'overlaps',
+ 'gt', 'gte', 'lt', 'lte', 'in',
+ 'startswith', 'istartswith', 'endswith', 'iendswith',
+ 'range', 'year', 'month', 'day', 'isnull', 'search',
+)
+
+
+def dprint(arg):
+ import re
+ import inspect
+ print re.match("^\s*dprint\(\s*(.+)\s*\)", inspect.stack()[1][4][0]).group(1) + ": " + repr(arg)
+
+
+
+class GeometryManager(models.Manager):
+ #def filter(self, *args, **kwargs):
+ # super(Manager, self).filter(*args, **kwargs)
+ # return self.get_query_set().filter(*args, **kwargs)
+
+ def get_query_set(self):
+ return GeoQuerySet(self.model)
+
+
+
+
+class BoundingBox:
+
+ def _geom(self):
+ return geomToWKT(self._g)
+
+ geom = property(_geom)
+
+ def _area(self):
+ return self._g.area()
+
+ area = property(_area)
+
+
+ def __init__(self, ne, sw):
+ """
+ Create a bounding box using two points
+ This points come from a JSON request, so they are strings
+ """
+ ne = [Decimal(i.strip(' ')) for i in ne[1:-1].split(',')]
+ sw = [Decimal(i.strip(' ')) for i in sw[1:-1].split(',')]
+ ne_lat = ne[0]
+ ne_lng = ne[1]
+ sw_lat = sw[0]
+ sw_lng = sw[1]
+ bb = 'POLYGON(('
+ bb += str(ne_lng) + " " + str(ne_lat) + ","
+ bb += str(ne_lng) + " " + str(sw_lat) + ","
+ bb += str(sw_lng) + " " + str(sw_lat) + ","
+ bb += str(sw_lng) + " " + str(ne_lat) + ","
+ bb += str(ne_lng) + " " + str(ne_lat)
+ bb += '))'
+ self._g = geomFromWKT(bb)
diff --git a/django/contrib/gis/db/__init__.py b/django/contrib/gis/db/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/django/contrib/gis/db/__init__.py
diff --git a/django/contrib/gis/db/models/__init__.py b/django/contrib/gis/db/models/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/django/contrib/gis/db/models/__init__.py
diff --git a/django/contrib/gis/db/models/fields/__init__.py b/django/contrib/gis/db/models/fields/__init__.py
new file mode 100644
index 0000000000..a0d4dad6e8
--- /dev/null
+++ b/django/contrib/gis/db/models/fields/__init__.py
@@ -0,0 +1,72 @@
+from django.db import models
+from django.db.models.fields import Field
+#from GeoTypes import Point
+
+# Creates the SQL to add the model to the database. Defaults to using an
+# SRID of 4326 (WGS84 Datum -- 'normal' lat/lon coordinates)
+def _add_geom(geom, srid, style, model, field, dim=2):
+ from django.db import backend
+
+ # Constructing the AddGeometryColumn(...) command -- the style
+ # object is passed in from the management module and is used
+ # to syntax highlight the command for 'sqlall'
+ sql = style.SQL_KEYWORD('SELECT ') + \
+ style.SQL_TABLE('AddGeometryColumn') + "('" + \
+ style.SQL_TABLE(model) + "', '" + \
+ style.SQL_FIELD(field) + "', " + \
+ style.SQL_FIELD(str(srid)) + ", '" + \
+ style.SQL_KEYWORD(geom) + "', " + \
+ style.SQL_KEYWORD(str(dim)) + \
+ ');'
+ return sql
+
+class GeometryField(Field):
+ """The base GIS field -- maps to an OpenGIS Geometry type."""
+
+ _geom = 'GEOMETRY'
+ _srid = 4326
+
+ def _post_create_sql(self, *args, **kwargs):
+ """Returns SQL that will be executed after the model has been created. Geometry
+ columns must be added after creation with the PostGIS AddGeometryColumn() function."""
+ return _add_geom(self._geom, self._srid, *args, **kwargs)
+
+ def get_db_prep_lookup(self, lookup_type, value):
+ "Returns field's value prepared for database lookup."
+ if lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search', 'overlaps'):
+ return [value]
+ elif lookup_type in ('range', 'in'):
+ return value
+ elif lookup_type in ('contains', 'icontains'):
+ return ["%%%s%%" % prep_for_like_query(value)]
+ elif lookup_type == 'iexact':
+ return [prep_for_like_query(value)]
+ elif lookup_type in ('startswith', 'istartswith'):
+ return ["%s%%" % prep_for_like_query(value)]
+ elif lookup_type in ('endswith', 'iendswith'):
+ return ["%%%s" % prep_for_like_query(value)]
+ elif lookup_type == 'isnull':
+ return []
+ elif lookup_type == 'year':
+ try:
+ value = int(value)
+ except ValueError:
+ raise ValueError("The __year lookup type requires an integer argument")
+ return ['%s-01-01 00:00:00' % value, '%s-12-31 23:59:59.999999' % value]
+ raise TypeError("Field has invalid lookup: %s" % lookup_type)
+
+ def get_db_prep_save(self, value):
+ return 'SRID=%d;%s' % (self._srid, value)
+
+
+class PointField(GeometryField):
+ _geom = 'POINT'
+
+class PolygonField(GeometryField):
+ _geom = 'POLYGON'
+
+class MultiPolygonField(GeometryField):
+ _geom = 'MULTIPOLYGON'
+
+class GeometryManager(models.Manager):
+ pass
diff --git a/django/core/management.py b/django/core/management.py
index 0a04a7e830..a78c9f91d4 100644
--- a/django/core/management.py
+++ b/django/core/management.py
@@ -386,6 +386,10 @@ def get_custom_sql_for_model(model):
output.append(statement + ";")
fp.close()
+ for f in opts.fields:
+ if hasattr(f, '_post_create_sql'):
+ output.append(f._post_create_sql(style, model._meta.db_table, f.column))
+
return output
def get_custom_sql(app):
diff --git a/django/db/backends/ado_mssql/creation.py b/django/db/backends/ado_mssql/creation.py
index 5158ba02f9..03af91c9af 100644
--- a/django/db/backends/ado_mssql/creation.py
+++ b/django/db/backends/ado_mssql/creation.py
@@ -11,7 +11,6 @@ DATA_TYPES = {
'ImageField': 'varchar(100)',
'IntegerField': 'int',
'IPAddressField': 'char(15)',
- 'ManyToManyField': None,
'NullBooleanField': 'bit',
'OneToOneField': 'int',
'PhoneNumberField': 'varchar(20)',
@@ -22,4 +21,5 @@ DATA_TYPES = {
'TextField': 'text',
'TimeField': 'time',
'USStateField': 'varchar(2)',
+ 'NoField': None,
}
diff --git a/django/db/backends/mysql/creation.py b/django/db/backends/mysql/creation.py
index 22ed901653..15741ad388 100644
--- a/django/db/backends/mysql/creation.py
+++ b/django/db/backends/mysql/creation.py
@@ -15,7 +15,6 @@ DATA_TYPES = {
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'char(15)',
- 'ManyToManyField': None,
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
@@ -26,4 +25,5 @@ DATA_TYPES = {
'TextField': 'longtext',
'TimeField': 'time',
'USStateField': 'varchar(2)',
+ 'NoField': None,
}
diff --git a/django/db/backends/oracle/creation.py b/django/db/backends/oracle/creation.py
index da65df172e..fc71df4c80 100644
--- a/django/db/backends/oracle/creation.py
+++ b/django/db/backends/oracle/creation.py
@@ -11,7 +11,6 @@ DATA_TYPES = {
'ImageField': 'varchar2(100)',
'IntegerField': 'integer',
'IPAddressField': 'char(15)',
- 'ManyToManyField': None,
'NullBooleanField': 'integer',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
@@ -22,4 +21,5 @@ DATA_TYPES = {
'TextField': 'long',
'TimeField': 'timestamp',
'USStateField': 'varchar(2)',
+ 'NoField': None,
}
diff --git a/django/db/backends/postgresql/creation.py b/django/db/backends/postgresql/creation.py
index 6c130f368e..43e421e455 100644
--- a/django/db/backends/postgresql/creation.py
+++ b/django/db/backends/postgresql/creation.py
@@ -15,7 +15,6 @@ DATA_TYPES = {
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'inet',
- 'ManyToManyField': None,
'NullBooleanField': 'boolean',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
@@ -26,4 +25,5 @@ DATA_TYPES = {
'TextField': 'text',
'TimeField': 'time',
'USStateField': 'varchar(2)',
+ 'NoField': None,
}
diff --git a/django/db/backends/sqlite3/creation.py b/django/db/backends/sqlite3/creation.py
index 77f570b2e8..cb23706c42 100644
--- a/django/db/backends/sqlite3/creation.py
+++ b/django/db/backends/sqlite3/creation.py
@@ -14,7 +14,6 @@ DATA_TYPES = {
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'char(15)',
- 'ManyToManyField': None,
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
@@ -25,4 +24,5 @@ DATA_TYPES = {
'TextField': 'text',
'TimeField': 'time',
'USStateField': 'varchar(2)',
+ 'NoField': None,
}
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index fad9c164c1..ffecfa1c1a 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -644,6 +644,9 @@ class ManyToManyField(RelatedField, Field):
msg = gettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.')
self.help_text = string_concat(self.help_text, ' ', msg)
+ def get_internal_type(self):
+ return "NoField"
+
def get_manipulator_field_objs(self):
if self.rel.raw_id_admin:
return [oldforms.RawIdAdminField]