Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
django
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
django
Commits
2bd1bbc4
Kaydet (Commit)
2bd1bbc4
authored
May 22, 2014
tarafından
Claude Paroz
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Converted GIS lookups to use the new Lookup API
Thanks Tim Graham, Anssi Kääriäinen and Marc Tamlyn for the reviews.
üst
4ef9618e
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
408 additions
and
485 deletions
+408
-485
base.py
django/contrib/gis/db/backends/base.py
+4
-13
operations.py
django/contrib/gis/db/backends/mysql/operations.py
+15
-32
operations.py
django/contrib/gis/db/backends/oracle/operations.py
+6
-0
operations.py
django/contrib/gis/db/backends/postgis/operations.py
+57
-234
operations.py
django/contrib/gis/db/backends/spatialite/operations.py
+20
-129
utils.py
django/contrib/gis/db/backends/utils.py
+19
-38
constants.py
django/contrib/gis/db/models/constants.py
+0
-15
fields.py
django/contrib/gis/db/models/fields.py
+6
-8
lookups.py
django/contrib/gis/db/models/lookups.py
+276
-14
query.py
django/contrib/gis/db/models/sql/query.py
+2
-2
1.8.txt
docs/releases/1.8.txt
+3
-0
No files found.
django/contrib/gis/db/backends/base.py
Dosyayı görüntüle @
2bd1bbc4
...
...
@@ -42,19 +42,19 @@ class BaseSpatialFeatures(object):
@property
def
supports_bbcontains_lookup
(
self
):
return
'bbcontains'
in
self
.
connection
.
ops
.
gis_
term
s
return
'bbcontains'
in
self
.
connection
.
ops
.
gis_
operator
s
@property
def
supports_contained_lookup
(
self
):
return
'contained'
in
self
.
connection
.
ops
.
gis_
term
s
return
'contained'
in
self
.
connection
.
ops
.
gis_
operator
s
@property
def
supports_dwithin_lookup
(
self
):
return
'dwithin'
in
self
.
connection
.
ops
.
distance_function
s
return
'dwithin'
in
self
.
connection
.
ops
.
gis_operator
s
@property
def
supports_relate_lookup
(
self
):
return
'relate'
in
self
.
connection
.
ops
.
gis_
term
s
return
'relate'
in
self
.
connection
.
ops
.
gis_
operator
s
# For each of those methods, the class will have a property named
# `has_<name>_method` (defined in __init__) which accesses connection.ops
...
...
@@ -97,12 +97,6 @@ class BaseSpatialOperations(object):
instantiated by each spatial database backend with the features
it has.
"""
distance_functions
=
{}
geometry_functions
=
{}
geometry_operators
=
{}
geography_operators
=
{}
geography_functions
=
{}
gis_terms
=
set
()
truncate_params
=
{}
# Quick booleans for the type of this spatial backend, and
...
...
@@ -215,9 +209,6 @@ class BaseSpatialOperations(object):
def
spatial_aggregate_sql
(
self
,
agg
):
raise
NotImplementedError
(
'Aggregate support not implemented for this spatial backend.'
)
def
spatial_lookup_sql
(
self
,
lvalue
,
lookup_type
,
value
,
field
):
raise
NotImplementedError
(
'subclasses of BaseSpatialOperations must a provide spatial_lookup_sql() method'
)
# Routines for getting the OGC-compliant models.
def
geometry_columns
(
self
):
raise
NotImplementedError
(
'subclasses of BaseSpatialOperations must a provide geometry_columns() method'
)
...
...
django/contrib/gis/db/backends/mysql/operations.py
Dosyayı görüntüle @
2bd1bbc4
...
...
@@ -2,6 +2,7 @@ from django.db.backends.mysql.base import DatabaseOperations
from
django.contrib.gis.db.backends.adapter
import
WKTAdapter
from
django.contrib.gis.db.backends.base
import
BaseSpatialOperations
from
django.contrib.gis.db.backends.utils
import
SpatialOperator
class
MySQLOperations
(
DatabaseOperations
,
BaseSpatialOperations
):
...
...
@@ -16,27 +17,25 @@ class MySQLOperations(DatabaseOperations, BaseSpatialOperations):
Adapter
=
WKTAdapter
Adaptor
=
Adapter
# Backwards-compatibility alias.
g
eometry_function
s
=
{
'bbcontains'
:
'MBRContains'
,
# For consistency w/PostGIS API
'bboverlaps'
:
'MBROverlaps'
,
# .. ..
'contained'
:
'MBRWithin'
,
# .. ..
'contains'
:
'MBRContains'
,
'disjoint'
:
'MBRDisjoint'
,
'equals'
:
'MBREqual'
,
'exact'
:
'MBREqual'
,
'intersects'
:
'MBRIntersects'
,
'overlaps'
:
'MBROverlaps'
,
'same_as'
:
'MBREqual'
,
'touches'
:
'MBRTouches'
,
'within'
:
'MBRWithin'
,
g
is_operator
s
=
{
'bbcontains'
:
SpatialOperator
(
func
=
'MBRContains'
)
,
# For consistency w/PostGIS API
'bboverlaps'
:
SpatialOperator
(
func
=
'MBROverlaps'
)
,
# .. ..
'contained'
:
SpatialOperator
(
func
=
'MBRWithin'
)
,
# .. ..
'contains'
:
SpatialOperator
(
func
=
'MBRContains'
)
,
'disjoint'
:
SpatialOperator
(
func
=
'MBRDisjoint'
)
,
'equals'
:
SpatialOperator
(
func
=
'MBREqual'
)
,
'exact'
:
SpatialOperator
(
func
=
'MBREqual'
)
,
'intersects'
:
SpatialOperator
(
func
=
'MBRIntersects'
)
,
'overlaps'
:
SpatialOperator
(
func
=
'MBROverlaps'
)
,
'same_as'
:
SpatialOperator
(
func
=
'MBREqual'
)
,
'touches'
:
SpatialOperator
(
func
=
'MBRTouches'
)
,
'within'
:
SpatialOperator
(
func
=
'MBRWithin'
)
,
}
gis_terms
=
set
(
geometry_functions
)
|
{
'isnull'
}
def
geo_db_type
(
self
,
f
):
return
f
.
geom_type
def
get_geom_placeholder
(
self
,
value
,
srid
):
def
get_geom_placeholder
(
self
,
f
,
value
):
"""
The placeholder here has to include MySQL's WKT constructor. Because
MySQL does not support spatial transformations, there is no need to
...
...
@@ -47,19 +46,3 @@ class MySQLOperations(DatabaseOperations, BaseSpatialOperations):
else
:
placeholder
=
'
%
s(
%%
s)'
%
self
.
from_text
return
placeholder
def
spatial_lookup_sql
(
self
,
lvalue
,
lookup_type
,
value
,
field
,
qn
):
geo_col
,
db_type
=
lvalue
lookup_info
=
self
.
geometry_functions
.
get
(
lookup_type
,
False
)
if
lookup_info
:
sql
=
"
%
s(
%
s,
%
s)"
%
(
lookup_info
,
geo_col
,
self
.
get_geom_placeholder
(
value
,
field
.
srid
))
return
sql
,
[]
# TODO: Is this really necessary? MySQL can't handle NULL geometries
# in its spatial indexes anyways.
if
lookup_type
==
'isnull'
:
return
"
%
s IS
%
sNULL"
%
(
geo_col
,
(
''
if
value
else
'NOT '
)),
[]
raise
TypeError
(
"Got invalid lookup_type:
%
s"
%
repr
(
lookup_type
))
django/contrib/gis/db/backends/oracle/operations.py
Dosyayı görüntüle @
2bd1bbc4
...
...
@@ -244,6 +244,12 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
else
:
return
'SDO_GEOMETRY(
%%
s,
%
s)'
%
f
.
srid
def
check_relate_argument
(
self
,
arg
):
masks
=
'TOUCH|OVERLAPBDYDISJOINT|OVERLAPBDYINTERSECT|EQUAL|INSIDE|COVEREDBY|CONTAINS|COVERS|ANYINTERACT|ON'
mask_regex
=
re
.
compile
(
r'^(
%
s)(\+(
%
s))*$'
%
(
masks
,
masks
),
re
.
I
)
if
not
self
.
mask_regex
.
match
(
arg
):
raise
ValueError
(
'Invalid SDO_RELATE mask: "
%
s"'
%
(
self
.
relate_func
,
arg
))
def
spatial_lookup_sql
(
self
,
lvalue
,
lookup_type
,
value
,
field
,
qn
):
"Returns the SQL WHERE clause for use in Oracle spatial SQL construction."
geo_col
,
db_type
=
lvalue
...
...
django/contrib/gis/db/backends/postgis/operations.py
Dosyayı görüntüle @
2bd1bbc4
import
re
from
decimal
import
Decimal
from
django.conf
import
settings
from
django.contrib.gis.db.backends.base
import
BaseSpatialOperations
from
django.contrib.gis.db.backends.utils
import
SpatialOperation
,
SpatialFunction
from
django.contrib.gis.db.backends.postgis.adapter
import
PostGISAdapter
from
django.contrib.gis.db.backends.utils
import
SpatialOperator
from
django.contrib.gis.geometry.backend
import
Geometry
from
django.contrib.gis.measure
import
Distance
from
django.core.exceptions
import
ImproperlyConfigured
from
django.db.backends.postgresql_psycopg2.base
import
DatabaseOperations
from
django.db.utils
import
ProgrammingError
from
django.utils
import
six
from
django.utils.functional
import
cached_property
from
.models
import
PostGISGeometryColumns
,
PostGISSpatialRefSys
#### Classes used in constructing PostGIS spatial SQL ####
class
PostGISOperator
(
SpatialOperation
):
"For PostGIS operators (e.g. `&&`, `~`)."
def
__init__
(
self
,
operator
):
super
(
PostGISOperator
,
self
)
.
__init__
(
operator
=
operator
)
class
PostGISFunction
(
SpatialFunction
):
"For PostGIS function calls (e.g., `ST_Contains(table, geom)`)."
def
__init__
(
self
,
prefix
,
function
,
**
kwargs
):
super
(
PostGISFunction
,
self
)
.
__init__
(
prefix
+
function
,
**
kwargs
)
class
PostGISFunctionParam
(
PostGISFunction
):
"For PostGIS functions that take another parameter (e.g. DWithin, Relate)."
sql_template
=
'
%(function)
s(
%(geo_col)
s,
%(geometry)
s,
%%
s)'
class
PostGISDistance
(
PostGISFunction
):
"For PostGIS distance operations."
dist_func
=
'Distance'
sql_template
=
'
%(function)
s(
%(geo_col)
s,
%(geometry)
s)
%(operator)
s
%%
s'
def
__init__
(
self
,
prefix
,
operator
):
super
(
PostGISDistance
,
self
)
.
__init__
(
prefix
,
self
.
dist_func
,
operator
=
operator
)
class
PostGISSpheroidDistance
(
PostGISFunction
):
"For PostGIS spherical distance operations (using the spheroid)."
dist_func
=
'distance_spheroid'
sql_template
=
'
%(function)
s(
%(geo_col)
s,
%(geometry)
s,
%%
s)
%(operator)
s
%%
s'
def
__init__
(
self
,
prefix
,
operator
):
# An extra parameter in `end_subst` is needed for the spheroid string.
super
(
PostGISSpheroidDistance
,
self
)
.
__init__
(
prefix
,
self
.
dist_func
,
operator
=
operator
)
class
PostGISOperator
(
SpatialOperator
):
def
__init__
(
self
,
geography
=
False
,
**
kwargs
):
# Only a subset of the operators and functions are available
# for the geography type.
self
.
geography
=
geography
super
(
PostGISOperator
,
self
)
.
__init__
(
**
kwargs
)
class
PostGISSphereDistance
(
PostGISDistance
):
"For PostGIS spherical distance operations."
dist_func
=
'distance_sphere'
def
as_sql
(
self
,
connection
,
lookup
,
*
args
):
if
lookup
.
lhs
.
source
.
geography
and
not
self
.
geography
:
raise
ValueError
(
'PostGIS geography does not support the "
%
s" '
'function/operator.'
%
(
self
.
func
or
self
.
op
,))
return
super
(
PostGISOperator
,
self
)
.
as_sql
(
connection
,
lookup
,
*
args
)
class
PostGISRelate
(
PostGISFunctionParam
):
"For PostGIS Relate(<geom>, <pattern>) calls."
pattern_regex
=
re
.
compile
(
r'^[012TF\*]{9}$'
)
class
PostGISDistanceOperator
(
PostGISOperator
):
sql_template
=
'
%(func)
s(
%(lhs)
s,
%(rhs)
s)
%(op)
s
%%
s'
def
__init__
(
self
,
prefix
,
pattern
):
if
not
self
.
pattern_regex
.
match
(
pattern
):
raise
ValueError
(
'Invalid intersection matrix pattern "
%
s".'
%
pattern
)
super
(
PostGISRelate
,
self
)
.
__init__
(
prefix
,
'Relate'
)
def
as_sql
(
self
,
connection
,
lookup
,
template_params
,
sql_params
):
if
not
lookup
.
lhs
.
source
.
geography
and
lookup
.
lhs
.
source
.
geodetic
(
connection
):
sql_template
=
self
.
sql_template
if
len
(
lookup
.
rhs
)
==
3
and
lookup
.
rhs
[
-
1
]
==
'spheroid'
:
template_params
.
update
({
'op'
:
self
.
op
,
'func'
:
'ST_Distance_Spheroid'
})
sql_template
=
'
%(func)
s(
%(lhs)
s,
%(rhs)
s,
%%
s)
%(op)
s
%%
s'
else
:
template_params
.
update
({
'op'
:
self
.
op
,
'func'
:
'ST_Distance_Sphere'
})
return
sql_template
%
template_params
,
sql_params
return
super
(
PostGISDistanceOperator
,
self
)
.
as_sql
(
connection
,
lookup
,
template_params
,
sql_params
)
class
PostGISOperations
(
DatabaseOperations
,
BaseSpatialOperations
):
...
...
@@ -82,104 +55,43 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
Adapter
=
PostGISAdapter
Adaptor
=
Adapter
# Backwards-compatibility alias.
gis_operators
=
{
'bbcontains'
:
PostGISOperator
(
op
=
'~'
),
'bboverlaps'
:
PostGISOperator
(
op
=
'&&'
,
geography
=
True
),
'contained'
:
PostGISOperator
(
op
=
'@'
),
'contains'
:
PostGISOperator
(
func
=
'ST_Contains'
),
'overlaps_left'
:
PostGISOperator
(
op
=
'&<'
),
'overlaps_right'
:
PostGISOperator
(
op
=
'&>'
),
'overlaps_below'
:
PostGISOperator
(
op
=
'&<|'
),
'overlaps_above'
:
PostGISOperator
(
op
=
'|&>'
),
'left'
:
PostGISOperator
(
op
=
'<<'
),
'right'
:
PostGISOperator
(
op
=
'>>'
),
'strictly_below'
:
PostGISOperator
(
op
=
'<<|'
),
'stricly_above'
:
PostGISOperator
(
op
=
'|>>'
),
'same_as'
:
PostGISOperator
(
op
=
'~='
),
'exact'
:
PostGISOperator
(
op
=
'~='
),
# alias of same_as
'contains_properly'
:
PostGISOperator
(
func
=
'ST_ContainsProperly'
),
'coveredby'
:
PostGISOperator
(
func
=
'ST_CoveredBy'
,
geography
=
True
),
'covers'
:
PostGISOperator
(
func
=
'ST_Covers'
,
geography
=
True
),
'crosses'
:
PostGISOperator
(
func
=
'ST_Crosses)'
),
'disjoint'
:
PostGISOperator
(
func
=
'ST_Disjoint'
),
'equals'
:
PostGISOperator
(
func
=
'ST_Equals'
),
'intersects'
:
PostGISOperator
(
func
=
'ST_Intersects'
,
geography
=
True
),
'overlaps'
:
PostGISOperator
(
func
=
'ST_Overlaps'
),
'relate'
:
PostGISOperator
(
func
=
'ST_Relate'
),
'touches'
:
PostGISOperator
(
func
=
'ST_Touches'
),
'within'
:
PostGISOperator
(
func
=
'ST_Within'
),
'dwithin'
:
PostGISOperator
(
func
=
'ST_DWithin'
,
geography
=
True
),
'distance_gt'
:
PostGISDistanceOperator
(
func
=
'ST_Distance'
,
op
=
'>'
,
geography
=
True
),
'distance_gte'
:
PostGISDistanceOperator
(
func
=
'ST_Distance'
,
op
=
'>='
,
geography
=
True
),
'distance_lt'
:
PostGISDistanceOperator
(
func
=
'ST_Distance'
,
op
=
'<'
,
geography
=
True
),
'distance_lte'
:
PostGISDistanceOperator
(
func
=
'ST_Distance'
,
op
=
'<='
,
geography
=
True
),
}
def
__init__
(
self
,
connection
):
super
(
PostGISOperations
,
self
)
.
__init__
(
connection
)
prefix
=
self
.
geom_func_prefix
# PostGIS-specific operators. The commented descriptions of these
# operators come from Section 7.6 of the PostGIS 1.4 documentation.
self
.
geometry_operators
=
{
# The "&<" operator returns true if A's bounding box overlaps or
# is to the left of B's bounding box.
'overlaps_left'
:
PostGISOperator
(
'&<'
),
# The "&>" operator returns true if A's bounding box overlaps or
# is to the right of B's bounding box.
'overlaps_right'
:
PostGISOperator
(
'&>'
),
# The "<<" operator returns true if A's bounding box is strictly
# to the left of B's bounding box.
'left'
:
PostGISOperator
(
'<<'
),
# The ">>" operator returns true if A's bounding box is strictly
# to the right of B's bounding box.
'right'
:
PostGISOperator
(
'>>'
),
# The "&<|" operator returns true if A's bounding box overlaps or
# is below B's bounding box.
'overlaps_below'
:
PostGISOperator
(
'&<|'
),
# The "|&>" operator returns true if A's bounding box overlaps or
# is above B's bounding box.
'overlaps_above'
:
PostGISOperator
(
'|&>'
),
# The "<<|" operator returns true if A's bounding box is strictly
# below B's bounding box.
'strictly_below'
:
PostGISOperator
(
'<<|'
),
# The "|>>" operator returns true if A's bounding box is strictly
# above B's bounding box.
'strictly_above'
:
PostGISOperator
(
'|>>'
),
# 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.
'same_as'
:
PostGISOperator
(
'~='
),
'exact'
:
PostGISOperator
(
'~='
),
# The "@" operator returns true if A's bounding box is completely contained
# by B's bounding box.
'contained'
:
PostGISOperator
(
'@'
),
# The "~" operator returns true if A's bounding box completely contains
# by B's bounding box.
'bbcontains'
:
PostGISOperator
(
'~'
),
# The "&&" operator returns true if A's bounding box overlaps
# B's bounding box.
'bboverlaps'
:
PostGISOperator
(
'&&'
),
}
self
.
geometry_functions
=
{
'equals'
:
PostGISFunction
(
prefix
,
'Equals'
),
'disjoint'
:
PostGISFunction
(
prefix
,
'Disjoint'
),
'touches'
:
PostGISFunction
(
prefix
,
'Touches'
),
'crosses'
:
PostGISFunction
(
prefix
,
'Crosses'
),
'within'
:
PostGISFunction
(
prefix
,
'Within'
),
'overlaps'
:
PostGISFunction
(
prefix
,
'Overlaps'
),
'contains'
:
PostGISFunction
(
prefix
,
'Contains'
),
'intersects'
:
PostGISFunction
(
prefix
,
'Intersects'
),
'relate'
:
(
PostGISRelate
,
six
.
string_types
),
'coveredby'
:
PostGISFunction
(
prefix
,
'CoveredBy'
),
'covers'
:
PostGISFunction
(
prefix
,
'Covers'
),
'contains_properly'
:
PostGISFunction
(
prefix
,
'ContainsProperly'
),
}
# Valid distance types and substitutions
dtypes
=
(
Decimal
,
Distance
,
float
)
+
six
.
integer_types
def
get_dist_ops
(
operator
):
"Returns operations for both regular and spherical distances."
return
{
'cartesian'
:
PostGISDistance
(
prefix
,
operator
),
'sphere'
:
PostGISSphereDistance
(
prefix
,
operator
),
'spheroid'
:
PostGISSpheroidDistance
(
prefix
,
operator
),
}
self
.
distance_functions
=
{
'distance_gt'
:
(
get_dist_ops
(
'>'
),
dtypes
),
'distance_gte'
:
(
get_dist_ops
(
'>='
),
dtypes
),
'distance_lt'
:
(
get_dist_ops
(
'<'
),
dtypes
),
'distance_lte'
:
(
get_dist_ops
(
'<='
),
dtypes
),
'dwithin'
:
(
PostGISFunctionParam
(
prefix
,
'DWithin'
),
dtypes
)
}
# Adding the distance functions to the geometries lookup.
self
.
geometry_functions
.
update
(
self
.
distance_functions
)
# 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
(
'&&'
),
}
# Creating a dictionary lookup of all GIS terms for PostGIS.
self
.
gis_terms
=
{
'isnull'
}
self
.
gis_terms
.
update
(
self
.
geometry_operators
)
self
.
gis_terms
.
update
(
self
.
geometry_functions
)
self
.
area
=
prefix
+
'Area'
self
.
bounding_circle
=
prefix
+
'MinimumBoundingCircle'
...
...
@@ -452,95 +364,6 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
else
:
raise
Exception
(
'Could not determine PROJ.4 version from PostGIS.'
)
def
num_params
(
self
,
lookup_type
,
num_param
):
"""
Helper routine that returns a boolean indicating whether the number of
parameters is correct for the lookup type.
"""
def
exactly_two
(
np
):
return
np
==
2
def
two_to_three
(
np
):
return
np
>=
2
and
np
<=
3
if
(
lookup_type
in
self
.
distance_functions
and
lookup_type
!=
'dwithin'
):
return
two_to_three
(
num_param
)
else
:
return
exactly_two
(
num_param
)
def
spatial_lookup_sql
(
self
,
lvalue
,
lookup_type
,
value
,
field
,
qn
):
"""
Constructs spatial SQL from the given lookup value tuple a
(alias, col, db_type), the lookup type string, lookup value, and
the geometry field.
"""
geo_col
,
db_type
=
lvalue
if
lookup_type
in
self
.
geometry_operators
:
if
field
.
geography
and
lookup_type
not
in
self
.
geography_operators
:
raise
ValueError
(
'PostGIS geography does not support the '
'"
%
s" lookup.'
%
lookup_type
)
# Handling a PostGIS operator.
op
=
self
.
geometry_operators
[
lookup_type
]
return
op
.
as_sql
(
geo_col
,
self
.
get_geom_placeholder
(
field
,
value
))
elif
lookup_type
in
self
.
geometry_functions
:
if
field
.
geography
and
lookup_type
not
in
self
.
geography_functions
:
raise
ValueError
(
'PostGIS geography type does not support the '
'"
%
s" lookup.'
%
lookup_type
)
# See if a PostGIS geometry function matches the lookup type.
tmp
=
self
.
geometry_functions
[
lookup_type
]
# Lookup types that are tuples take tuple arguments, e.g., 'relate' and
# distance lookups.
if
isinstance
(
tmp
,
tuple
):
# First element of tuple is the PostGISOperation instance, and the
# second element is either the type or a tuple of acceptable types
# that may passed in as further parameters for the lookup type.
op
,
arg_type
=
tmp
# Ensuring that a tuple _value_ was passed in from the user
if
not
isinstance
(
value
,
(
tuple
,
list
)):
raise
ValueError
(
'Tuple required for `
%
s` lookup type.'
%
lookup_type
)
# Geometry is first element of lookup tuple.
geom
=
value
[
0
]
# Number of valid tuple parameters depends on the lookup type.
nparams
=
len
(
value
)
if
not
self
.
num_params
(
lookup_type
,
nparams
):
raise
ValueError
(
'Incorrect number of parameters given for `
%
s` lookup type.'
%
lookup_type
)
# Ensuring the argument type matches what we expect.
if
not
isinstance
(
value
[
1
],
arg_type
):
raise
ValueError
(
'Argument type should be
%
s, got
%
s instead.'
%
(
arg_type
,
type
(
value
[
1
])))
# For lookup type `relate`, the op instance is not yet created (has
# to be instantiated here to check the pattern parameter).
if
lookup_type
==
'relate'
:
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
):
# Setting up the geodetic operation appropriately.
if
nparams
==
3
and
value
[
2
]
==
'spheroid'
:
op
=
op
[
'spheroid'
]
else
:
op
=
op
[
'sphere'
]
else
:
op
=
op
[
'cartesian'
]
else
:
op
=
tmp
geom
=
value
# Calling the `as_sql` function on the operation instance.
return
op
.
as_sql
(
geo_col
,
self
.
get_geom_placeholder
(
field
,
geom
))
elif
lookup_type
==
'isnull'
:
# Handling 'isnull' lookup type
return
"
%
s IS
%
sNULL"
%
(
geo_col
,
(
''
if
value
else
'NOT '
)),
[]
raise
TypeError
(
"Got invalid lookup_type:
%
s"
%
repr
(
lookup_type
))
def
spatial_aggregate_sql
(
self
,
agg
):
"""
Returns the spatial aggregate SQL template and function for the
...
...
django/contrib/gis/db/backends/spatialite/operations.py
Dosyayı görüntüle @
2bd1bbc4
import
re
import
sys
from
decimal
import
Decimal
from
django.contrib.gis.db.backends.base
import
BaseSpatialOperations
from
django.contrib.gis.db.backends.utils
import
SpatialOperat
ion
,
SpatialFunction
from
django.contrib.gis.db.backends.utils
import
SpatialOperat
or
from
django.contrib.gis.db.backends.spatialite.adapter
import
SpatiaLiteAdapter
from
django.contrib.gis.geometry.backend
import
Geometry
from
django.contrib.gis.measure
import
Distance
...
...
@@ -14,52 +13,6 @@ from django.utils import six
from
django.utils.functional
import
cached_property
class
SpatiaLiteOperator
(
SpatialOperation
):
"For SpatiaLite operators (e.g. `&&`, `~`)."
def
__init__
(
self
,
operator
):
super
(
SpatiaLiteOperator
,
self
)
.
__init__
(
operator
=
operator
)
class
SpatiaLiteFunction
(
SpatialFunction
):
"For SpatiaLite function calls."
def
__init__
(
self
,
function
,
**
kwargs
):
super
(
SpatiaLiteFunction
,
self
)
.
__init__
(
function
,
**
kwargs
)
class
SpatiaLiteFunctionParam
(
SpatiaLiteFunction
):
"For SpatiaLite functions that take another parameter."
sql_template
=
'
%(function)
s(
%(geo_col)
s,
%(geometry)
s,
%%
s)'
class
SpatiaLiteDistance
(
SpatiaLiteFunction
):
"For SpatiaLite distance operations."
dist_func
=
'Distance'
sql_template
=
'
%(function)
s(
%(geo_col)
s,
%(geometry)
s)
%(operator)
s
%%
s'
def
__init__
(
self
,
operator
):
super
(
SpatiaLiteDistance
,
self
)
.
__init__
(
self
.
dist_func
,
operator
=
operator
)
class
SpatiaLiteRelate
(
SpatiaLiteFunctionParam
):
"For SpatiaLite Relate(<geom>, <pattern>) calls."
pattern_regex
=
re
.
compile
(
r'^[012TF\*]{9}$'
)
def
__init__
(
self
,
pattern
):
if
not
self
.
pattern_regex
.
match
(
pattern
):
raise
ValueError
(
'Invalid intersection matrix pattern "
%
s".'
%
pattern
)
super
(
SpatiaLiteRelate
,
self
)
.
__init__
(
'Relate'
)
# Valid distance types and substitutions
dtypes
=
(
Decimal
,
Distance
,
float
)
+
six
.
integer_types
def
get_dist_ops
(
operator
):
"Returns operations for regular distances; spherical distances are not currently supported."
return
(
SpatiaLiteDistance
(
operator
),)
class
SpatiaLiteOperations
(
DatabaseOperations
,
BaseSpatialOperations
):
compiler_module
=
'django.contrib.gis.db.models.sql.compiler'
name
=
'spatialite'
...
...
@@ -101,41 +54,31 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
from_wkb
=
'GeomFromWKB'
select
=
'AsText(
%
s)'
g
eometry_function
s
=
{
'equals'
:
Spatia
LiteFunction
(
'Equals'
),
'disjoint'
:
Spatia
LiteFunction
(
'Disjoint'
),
'touches'
:
Spatia
LiteFunction
(
'Touches'
),
'crosses'
:
Spatia
LiteFunction
(
'Crosses'
),
'within'
:
Spatia
LiteFunction
(
'Within'
),
'overlaps'
:
Spatia
LiteFunction
(
'Overlaps'
),
'contains'
:
Spatia
LiteFunction
(
'Contains'
),
'intersects'
:
Spatia
LiteFunction
(
'Intersects'
),
'relate'
:
(
SpatiaLiteRelate
,
six
.
string_types
),
g
is_operator
s
=
{
'equals'
:
Spatia
lOperator
(
func
=
'Equals'
),
'disjoint'
:
Spatia
lOperator
(
func
=
'Disjoint'
),
'touches'
:
Spatia
lOperator
(
func
=
'Touches'
),
'crosses'
:
Spatia
lOperator
(
func
=
'Crosses'
),
'within'
:
Spatia
lOperator
(
func
=
'Within'
),
'overlaps'
:
Spatia
lOperator
(
func
=
'Overlaps'
),
'contains'
:
Spatia
lOperator
(
func
=
'Contains'
),
'intersects'
:
Spatia
lOperator
(
func
=
'Intersects'
),
'relate'
:
SpatialOperator
(
func
=
'Relate'
),
# Returns true if B's bounding box completely contains A's bounding box.
'contained'
:
Spatia
LiteFunction
(
'MbrWithin'
),
'contained'
:
Spatia
lOperator
(
func
=
'MbrWithin'
),
# Returns true if A's bounding box completely contains B's bounding box.
'bbcontains'
:
Spatia
LiteFunction
(
'MbrContains'
),
'bbcontains'
:
Spatia
lOperator
(
func
=
'MbrContains'
),
# Returns true if A's bounding box overlaps B's bounding box.
'bboverlaps'
:
Spatia
LiteFunction
(
'MbrOverlaps'
),
'bboverlaps'
:
Spatia
lOperator
(
func
=
'MbrOverlaps'
),
# These are implemented here as synonyms for Equals
'same_as'
:
SpatiaLiteFunction
(
'Equals'
),
'exact'
:
SpatiaLiteFunction
(
'Equals'
),
}
'same_as'
:
SpatialOperator
(
func
=
'Equals'
),
'exact'
:
SpatialOperator
(
func
=
'Equals'
),
distance_functions
=
{
'distance_gt'
:
(
get_dist_ops
(
'>'
),
dtypes
),
'distance_gte'
:
(
get_dist_ops
(
'>='
),
dtypes
),
'distance_lt'
:
(
get_dist_ops
(
'<'
),
dtypes
),
'distance_lte'
:
(
get_dist_ops
(
'<='
),
dtypes
),
'distance_gt'
:
SpatialOperator
(
func
=
'Distance'
,
op
=
'>'
),
'distance_gte'
:
SpatialOperator
(
func
=
'Distance'
,
op
=
'>='
),
'distance_lt'
:
SpatialOperator
(
func
=
'Distance'
,
op
=
'<'
),
'distance_lte'
:
SpatialOperator
(
func
=
'Distance'
,
op
=
'<='
),
}
geometry_functions
.
update
(
distance_functions
)
def
__init__
(
self
,
connection
):
super
(
DatabaseOperations
,
self
)
.
__init__
(
connection
)
# Creating the GIS terms dictionary.
self
.
gis_terms
=
{
'isnull'
}
self
.
gis_terms
.
update
(
self
.
geometry_functions
)
@cached_property
def
spatial_version
(
self
):
...
...
@@ -316,58 +259,6 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
sql_function
=
getattr
(
self
,
agg_name
)
return
sql_template
,
sql_function
def
spatial_lookup_sql
(
self
,
lvalue
,
lookup_type
,
value
,
field
,
qn
):
"""
Returns the SpatiaLite-specific SQL for the given lookup value
[a tuple of (alias, column, db_type)], lookup type, lookup
value, the model field, and the quoting function.
"""
geo_col
,
db_type
=
lvalue
if
lookup_type
in
self
.
geometry_functions
:
# See if a SpatiaLite geometry function matches the lookup type.
tmp
=
self
.
geometry_functions
[
lookup_type
]
# Lookup types that are tuples take tuple arguments, e.g., 'relate' and
# distance lookups.
if
isinstance
(
tmp
,
tuple
):
# First element of tuple is the SpatiaLiteOperation instance, and the
# second element is either the type or a tuple of acceptable types
# that may passed in as further parameters for the lookup type.
op
,
arg_type
=
tmp
# Ensuring that a tuple _value_ was passed in from the user
if
not
isinstance
(
value
,
(
tuple
,
list
)):
raise
ValueError
(
'Tuple required for `
%
s` lookup type.'
%
lookup_type
)
# Geometry is first element of lookup tuple.
geom
=
value
[
0
]
# Number of valid tuple parameters depends on the lookup type.
if
len
(
value
)
!=
2
:
raise
ValueError
(
'Incorrect number of parameters given for `
%
s` lookup type.'
%
lookup_type
)
# Ensuring the argument type matches what we expect.
if
not
isinstance
(
value
[
1
],
arg_type
):
raise
ValueError
(
'Argument type should be
%
s, got
%
s instead.'
%
(
arg_type
,
type
(
value
[
1
])))
# For lookup type `relate`, the op instance is not yet created (has
# to be instantiated here to check the pattern parameter).
if
lookup_type
==
'relate'
:
op
=
op
(
value
[
1
])
elif
lookup_type
in
self
.
distance_functions
:
op
=
op
[
0
]
else
:
op
=
tmp
geom
=
value
# Calling the `as_sql` function on the operation instance.
return
op
.
as_sql
(
geo_col
,
self
.
get_geom_placeholder
(
field
,
geom
))
elif
lookup_type
==
'isnull'
:
# Handling 'isnull' lookup type
return
"
%
s IS
%
sNULL"
%
(
geo_col
,
(
''
if
value
else
'NOT '
)),
[]
raise
TypeError
(
"Got invalid lookup_type:
%
s"
%
repr
(
lookup_type
))
# Routines for getting the OGC-compliant models.
def
geometry_columns
(
self
):
from
django.contrib.gis.db.backends.spatialite.models
import
SpatialiteGeometryColumns
...
...
django/contrib/gis/db/backends/utils.py
Dosyayı görüntüle @
2bd1bbc4
...
...
@@ -4,43 +4,24 @@ backends.
"""
class
SpatialOperat
ion
(
object
):
class
SpatialOperat
or
(
object
):
"""
Base class for generating spatial SQL
.
Class encapsulating the behavior specific to a GIS operation (used by lookups)
.
"""
sql_template
=
'
%(geo_col)
s
%(operator)
s
%(geometry)
s'
def
__init__
(
self
,
function
=
''
,
operator
=
''
,
result
=
''
,
**
kwargs
):
self
.
function
=
function
self
.
operator
=
operator
self
.
result
=
result
self
.
extra
=
kwargs
def
as_sql
(
self
,
geo_col
,
geometry
=
'
%
s'
):
return
self
.
sql_template
%
self
.
params
(
geo_col
,
geometry
),
[]
def
params
(
self
,
geo_col
,
geometry
):
params
=
{
'function'
:
self
.
function
,
'geo_col'
:
geo_col
,
'geometry'
:
geometry
,
'operator'
:
self
.
operator
,
'result'
:
self
.
result
,
}
params
.
update
(
self
.
extra
)
return
params
class
SpatialFunction
(
SpatialOperation
):
"""
Base class for generating spatial SQL related to a function.
"""
sql_template
=
'
%(function)
s(
%(geo_col)
s,
%(geometry)
s)'
def
__init__
(
self
,
func
,
result
=
''
,
operator
=
''
,
**
kwargs
):
# Getting the function prefix.
default
=
{
'function'
:
func
,
'operator'
:
operator
,
'result'
:
result
}
kwargs
.
update
(
default
)
super
(
SpatialFunction
,
self
)
.
__init__
(
**
kwargs
)
sql_template
=
None
def
__init__
(
self
,
op
=
None
,
func
=
None
):
self
.
op
=
op
self
.
func
=
func
@property
def
default_template
(
self
):
if
self
.
func
:
return
'
%(func)
s(
%(lhs)
s,
%(rhs)
s)'
else
:
return
'
%(lhs)
s
%(op)
s
%(rhs)
s'
def
as_sql
(
self
,
connection
,
lookup
,
template_params
,
sql_params
):
sql_template
=
self
.
sql_template
or
lookup
.
sql_template
or
self
.
default_template
template_params
.
update
({
'op'
:
self
.
op
,
'func'
:
self
.
func
})
return
sql_template
%
template_params
,
sql_params
django/contrib/gis/db/models/constants.py
deleted
100644 → 0
Dosyayı görüntüle @
4ef9618e
from
django.db.models.sql.constants
import
QUERY_TERMS
GIS_LOOKUPS
=
{
'bbcontains'
,
'bboverlaps'
,
'contained'
,
'contains'
,
'contains_properly'
,
'coveredby'
,
'covers'
,
'crosses'
,
'disjoint'
,
'distance_gt'
,
'distance_gte'
,
'distance_lt'
,
'distance_lte'
,
'dwithin'
,
'equals'
,
'exact'
,
'intersects'
,
'overlaps'
,
'relate'
,
'same_as'
,
'touches'
,
'within'
,
'left'
,
'right'
,
'overlaps_left'
,
'overlaps_right'
,
'overlaps_above'
,
'overlaps_below'
,
'strictly_above'
,
'strictly_below'
}
ALL_TERMS
=
GIS_LOOKUPS
|
QUERY_TERMS
__all__
=
[
'ALL_TERMS'
,
'GIS_LOOKUPS'
]
django/contrib/gis/db/models/fields.py
Dosyayı görüntüle @
2bd1bbc4
...
...
@@ -2,8 +2,7 @@ from django.db.models.fields import Field
from
django.db.models.sql.expressions
import
SQLEvaluator
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.contrib.gis
import
forms
from
django.contrib.gis.db.models.constants
import
GIS_LOOKUPS
from
django.contrib.gis.db.models.lookups
import
GISLookup
from
django.contrib.gis.db.models.lookups
import
gis_lookups
from
django.contrib.gis.db.models.proxy
import
GeometryProxy
from
django.contrib.gis.geometry.backend
import
Geometry
,
GeometryException
from
django.utils
import
six
...
...
@@ -243,16 +242,15 @@ class GeometryField(Field):
parameters into the correct units for the coordinate system of the
field.
"""
if
lookup_type
in
connection
.
ops
.
gis_terms
:
# special case for isnull lookup
if
lookup_type
==
'isnull'
:
return
[]
elif
lookup_type
in
self
.
class_lookups
:
# Populating the parameters list, and wrapping the Geometry
# with the Adapter of the spatial backend.
if
isinstance
(
value
,
(
tuple
,
list
)):
params
=
[
connection
.
ops
.
Adapter
(
value
[
0
])]
if
lookup_type
in
connection
.
ops
.
distance_functions
:
if
self
.
class_lookups
[
lookup_type
]
.
distance
:
# Getting the distance parameter in the units of the field.
params
+=
self
.
get_distance
(
value
[
1
:],
lookup_type
,
connection
)
elif
lookup_type
in
connection
.
ops
.
truncate_params
:
...
...
@@ -291,9 +289,9 @@ class GeometryField(Field):
"""
return
connection
.
ops
.
get_geom_placeholder
(
self
,
value
)
for
lookup_name
in
GIS_LOOKUPS
:
lookup
=
type
(
lookup_name
,
(
GISLookup
,),
{
'lookup_name'
:
lookup_name
})
GeometryField
.
register_lookup
(
lookup
)
for
klass
in
gis_lookups
.
values
():
GeometryField
.
register_lookup
(
klass
)
# The OpenGIS Geometry Type Fields
...
...
django/contrib/gis/db/models/lookups.py
Dosyayı görüntüle @
2bd1bbc4
from
__future__
import
unicode_literals
import
re
from
django.db.models.constants
import
LOOKUP_SEP
from
django.db.models.fields
import
FieldDoesNotExist
from
django.db.models.lookups
import
Lookup
from
django.db.models.sql.expressions
import
SQLEvaluator
from
django.utils
import
six
gis_lookups
=
{}
class
GISLookup
(
Lookup
):
sql_template
=
None
transform_func
=
None
distance
=
False
@classmethod
def
_check_geo_field
(
cls
,
opts
,
lookup
):
"""
...
...
@@ -45,10 +55,19 @@ class GISLookup(Lookup):
else
:
return
False
def
as_sql
(
self
,
qn
,
connection
):
# We use the same approach as was used by GeoWhereNode. It would
# be a good idea to upgrade GIS to use similar code that is used
# for other lookups.
def
get_db_prep_lookup
(
self
,
value
,
connection
):
# get_db_prep_lookup is called by process_rhs from super class
if
isinstance
(
value
,
(
tuple
,
list
)):
# First param is assumed to be the geometric object
params
=
[
connection
.
ops
.
Adapter
(
value
[
0
])]
+
list
(
value
)[
1
:]
else
:
params
=
[
connection
.
ops
.
Adapter
(
value
)]
return
(
'
%
s'
,
params
)
def
process_rhs
(
self
,
qn
,
connection
):
rhs
,
rhs_params
=
super
(
GISLookup
,
self
)
.
process_rhs
(
qn
,
connection
)
geom
=
self
.
rhs
if
isinstance
(
self
.
rhs
,
SQLEvaluator
):
# Make sure the F Expression destination field exists, and
# set an `srid` attribute with the same as that of the
...
...
@@ -57,13 +76,256 @@ class GISLookup(Lookup):
if
not
geo_fld
:
raise
ValueError
(
'No geographic field found in expression.'
)
self
.
rhs
.
srid
=
geo_fld
.
srid
db_type
=
self
.
lhs
.
output_field
.
db_type
(
connection
=
connection
)
params
=
self
.
lhs
.
output_field
.
get_db_prep_lookup
(
self
.
lookup_name
,
self
.
rhs
,
connection
=
connection
)
lhs_sql
,
lhs_params
=
self
.
process_lhs
(
qn
,
connection
)
# lhs_params not currently supported.
assert
not
lhs_params
data
=
(
lhs_sql
,
db_type
)
spatial_sql
,
spatial_params
=
connection
.
ops
.
spatial_lookup_sql
(
data
,
self
.
lookup_name
,
self
.
rhs
,
self
.
lhs
.
output_field
,
qn
)
return
spatial_sql
,
spatial_params
+
params
elif
isinstance
(
self
.
rhs
,
(
list
,
tuple
)):
geom
=
self
.
rhs
[
0
]
rhs
=
connection
.
ops
.
get_geom_placeholder
(
self
.
lhs
.
source
,
geom
)
return
rhs
,
rhs_params
def
as_sql
(
self
,
qn
,
connection
):
lhs_sql
,
sql_params
=
self
.
process_lhs
(
qn
,
connection
)
rhs_sql
,
rhs_params
=
self
.
process_rhs
(
qn
,
connection
)
sql_params
.
extend
(
rhs_params
)
template_params
=
{
'lhs'
:
lhs_sql
,
'rhs'
:
rhs_sql
}
backend_op
=
connection
.
ops
.
gis_operators
[
self
.
lookup_name
]
return
backend_op
.
as_sql
(
connection
,
self
,
template_params
,
sql_params
)
# ------------------
# Geometry operators
# ------------------
class
OverlapsLeftLookup
(
GISLookup
):
"""
The overlaps_left operator returns true if A's bounding box overlaps or is to the
left of B's bounding box.
"""
lookup_name
=
'overlaps_left'
gis_lookups
[
'overlaps_left'
]
=
OverlapsLeftLookup
class
OverlapsRightLookup
(
GISLookup
):
"""
The 'overlaps_right' operator returns true if A's bounding box overlaps or is to the
right of B's bounding box.
"""
lookup_name
=
'overlaps_right'
gis_lookups
[
'overlaps_right'
]
=
OverlapsRightLookup
class
OverlapsBelowLookup
(
GISLookup
):
"""
The 'overlaps_below' operator returns true if A's bounding box overlaps or is below
B's bounding box.
"""
lookup_name
=
'overlaps_below'
gis_lookups
[
'overlaps_below'
]
=
OverlapsBelowLookup
class
OverlapsAboveLookup
(
GISLookup
):
"""
The 'overlaps_above' operator returns true if A's bounding box overlaps or is above
B's bounding box.
"""
lookup_name
=
'overlaps_above'
gis_lookups
[
'overlaps_above'
]
=
OverlapsAboveLookup
class
LeftLookup
(
GISLookup
):
"""
The 'left' operator returns true if A's bounding box is strictly to the left
of B's bounding box.
"""
lookup_name
=
'left'
gis_lookups
[
'left'
]
=
LeftLookup
class
RightLookup
(
GISLookup
):
"""
The 'right' operator returns true if A's bounding box is strictly to the right
of B's bounding box.
"""
lookup_name
=
'right'
gis_lookups
[
'right'
]
=
RightLookup
class
StrictlyBelowLookup
(
GISLookup
):
"""
The 'strictly_below' operator returns true if A's bounding box is strictly below B's
bounding box.
"""
lookup_name
=
'strictly_below'
gis_lookups
[
'strictly_below'
]
=
StrictlyBelowLookup
class
StrictlyAboveLookup
(
GISLookup
):
"""
The 'strictly_above' operator returns true if A's bounding box is strictly above B's
bounding box.
"""
lookup_name
=
'strictly_above'
gis_lookups
[
'strictly_above'
]
=
StrictlyAboveLookup
class
SameAsLookup
(
GISLookup
):
"""
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.
"""
lookup_name
=
'same_as'
gis_lookups
[
'same_as'
]
=
SameAsLookup
class
ExactLookup
(
SameAsLookup
):
# Alias of same_as
lookup_name
=
'exact'
gis_lookups
[
'exact'
]
=
ExactLookup
class
BBContainsLookup
(
GISLookup
):
"""
The 'bbcontains' operator returns true if A's bounding box completely contains
by B's bounding box.
"""
lookup_name
=
'bbcontains'
gis_lookups
[
'bbcontains'
]
=
BBContainsLookup
class
BBOverlapsLookup
(
GISLookup
):
"""
The 'bboverlaps' operator returns true if A's bounding box overlaps B's bounding box.
"""
lookup_name
=
'bboverlaps'
gis_lookups
[
'bboverlaps'
]
=
BBOverlapsLookup
class
ContainedLookup
(
GISLookup
):
"""
The 'contained' operator returns true if A's bounding box is completely contained
by B's bounding box.
"""
lookup_name
=
'contained'
gis_lookups
[
'contained'
]
=
ContainedLookup
# ------------------
# Geometry functions
# ------------------
class
ContainsLookup
(
GISLookup
):
lookup_name
=
'contains'
gis_lookups
[
'contains'
]
=
ContainsLookup
class
ContainsProperlyLookup
(
GISLookup
):
lookup_name
=
'contains_properly'
gis_lookups
[
'contains_properly'
]
=
ContainsProperlyLookup
class
CoveredByLookup
(
GISLookup
):
lookup_name
=
'coveredby'
gis_lookups
[
'coveredby'
]
=
CoveredByLookup
class
CoversLookup
(
GISLookup
):
lookup_name
=
'covers'
gis_lookups
[
'covers'
]
=
CoversLookup
class
CrossesLookup
(
GISLookup
):
lookup_name
=
'crosses'
gis_lookups
[
'crosses'
]
=
CrossesLookup
class
DisjointLookup
(
GISLookup
):
lookup_name
=
'disjoint'
gis_lookups
[
'disjoint'
]
=
DisjointLookup
class
EqualsLookup
(
GISLookup
):
lookup_name
=
'equals'
gis_lookups
[
'equals'
]
=
EqualsLookup
class
IntersectsLookup
(
GISLookup
):
lookup_name
=
'intersects'
gis_lookups
[
'intersects'
]
=
IntersectsLookup
class
OverlapsLookup
(
GISLookup
):
lookup_name
=
'overlaps'
gis_lookups
[
'overlaps'
]
=
OverlapsLookup
class
RelateLookup
(
GISLookup
):
lookup_name
=
'relate'
sql_template
=
'
%(func)
s(
%(lhs)
s,
%(rhs)
s,
%%
s)'
pattern_regex
=
re
.
compile
(
r'^[012TF\*]{9}$'
)
def
get_db_prep_lookup
(
self
,
value
,
connection
):
if
len
(
value
)
!=
2
:
raise
ValueError
(
'relate must be passed a two-tuple'
)
# Check the pattern argument
backend_op
=
connection
.
ops
.
gis_operators
[
self
.
lookup_name
]
if
hasattr
(
backend_op
,
'check_relate_argument'
):
backend_op
.
check_relate_argument
(
value
[
1
])
else
:
pattern
=
value
[
1
]
if
not
isinstance
(
pattern
,
six
.
string_types
)
or
not
self
.
pattern_regex
.
match
(
pattern
):
raise
ValueError
(
'Invalid intersection matrix pattern "
%
s".'
%
pattern
)
return
super
(
RelateLookup
,
self
)
.
get_db_prep_lookup
(
value
,
connection
)
gis_lookups
[
'relate'
]
=
RelateLookup
class
TouchesLookup
(
GISLookup
):
lookup_name
=
'touches'
gis_lookups
[
'touches'
]
=
TouchesLookup
class
WithinLookup
(
GISLookup
):
lookup_name
=
'within'
gis_lookups
[
'within'
]
=
WithinLookup
class
DistanceLookupBase
(
GISLookup
):
distance
=
True
sql_template
=
'
%(func)
s(
%(lhs)
s,
%(rhs)
s)
%(op)
s
%%
s'
def
get_db_prep_lookup
(
self
,
value
,
connection
):
if
isinstance
(
value
,
(
tuple
,
list
)):
if
not
2
<=
len
(
value
)
<=
3
:
raise
ValueError
(
"2 or 3-element tuple required for '
%
s' lookup."
%
self
.
lookup_name
)
params
=
[
connection
.
ops
.
Adapter
(
value
[
0
])]
# Getting the distance parameter in the units of the field.
params
+=
connection
.
ops
.
get_distance
(
self
.
lhs
.
output_field
,
value
[
1
:],
self
.
lookup_name
)
return
(
'
%
s'
,
params
)
else
:
return
super
(
DistanceLookupBase
,
self
)
.
get_db_prep_lookup
(
value
,
connection
)
class
DWithinLookup
(
DistanceLookupBase
):
lookup_name
=
'dwithin'
sql_template
=
'
%(func)
s(
%(lhs)
s,
%(rhs)
s,
%%
s)'
gis_lookups
[
'dwithin'
]
=
DWithinLookup
class
DistanceGTLookup
(
DistanceLookupBase
):
lookup_name
=
'distance_gt'
gis_lookups
[
'distance_gt'
]
=
DistanceGTLookup
class
DistanceGTELookup
(
DistanceLookupBase
):
lookup_name
=
'distance_gte'
gis_lookups
[
'distance_gte'
]
=
DistanceGTELookup
class
DistanceLTLookup
(
DistanceLookupBase
):
lookup_name
=
'distance_lt'
gis_lookups
[
'distance_lt'
]
=
DistanceLTLookup
class
DistanceLTELookup
(
DistanceLookupBase
):
lookup_name
=
'distance_lte'
gis_lookups
[
'distance_lte'
]
=
DistanceLTELookup
django/contrib/gis/db/models/sql/query.py
Dosyayı görüntüle @
2bd1bbc4
from
django.db
import
connections
from
django.db.models.query
import
sql
from
django.db.models.sql.constants
import
QUERY_TERMS
from
django.contrib.gis.db.models.constants
import
ALL_TERMS
from
django.contrib.gis.db.models.fields
import
GeometryField
from
django.contrib.gis.db.models.lookups
import
GISLookup
from
django.contrib.gis.db.models.sql
import
aggregates
as
gis_aggregates
...
...
@@ -13,7 +13,7 @@ class GeoQuery(sql.Query):
A single spatial SQL query.
"""
# Overridding the valid query terms.
query_terms
=
ALL_TERMS
query_terms
=
QUERY_TERMS
|
set
(
GeometryField
.
class_lookups
.
keys
())
aggregates_module
=
gis_aggregates
compiler
=
'GeoSQLCompiler'
...
...
docs/releases/1.8.txt
Dosyayı görüntüle @
2bd1bbc4
...
...
@@ -612,6 +612,9 @@ Miscellaneous
:func:`~django.core.urlresolvers.reverse_lazy` now return Unicode strings
instead of byte strings.
* GIS-specific lookups have been refactored to use the
:class:`django.db.models.Lookup` API.
.. _deprecated-features-1.8:
Features deprecated in 1.8
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment