Ajoutez des fichiers projet.

This commit is contained in:
Ambulance Clerc
2021-12-18 18:43:17 +01:00
parent 3c4d48ed26
commit 46254605fc
4842 changed files with 732322 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
class WKTAdapter:
"""
An adaptor for Geometries sent to the MySQL and Oracle database backends.
"""
def __init__(self, geom):
self.wkt = geom.wkt
self.srid = geom.srid
def __eq__(self, other):
return (
isinstance(other, WKTAdapter) and
self.wkt == other.wkt and self.srid == other.srid
)
def __hash__(self):
return hash((self.wkt, self.srid))
def __str__(self):
return self.wkt
@classmethod
def _fix_polygon(cls, poly):
# Hook for Oracle.
return poly

View File

@@ -0,0 +1,111 @@
import re
from django.contrib.gis.db import models
class BaseSpatialFeatures:
gis_enabled = True
# Does the database contain a SpatialRefSys model to store SRID information?
has_spatialrefsys_table = True
# Does the backend support the django.contrib.gis.utils.add_srs_entry() utility?
supports_add_srs_entry = True
# Does the backend introspect GeometryField to its subtypes?
supports_geometry_field_introspection = True
# Does the database have a geography type?
supports_geography = False
# Does the backend support storing 3D geometries?
supports_3d_storage = False
# Reference implementation of 3D functions is:
# https://postgis.net/docs/PostGIS_Special_Functions_Index.html#PostGIS_3D_Functions
supports_3d_functions = False
# Does the database support SRID transform operations?
supports_transform = True
# Can geometry fields be null?
supports_null_geometries = True
# Are empty geometries supported?
supports_empty_geometries = False
# Can the function be applied on geodetic coordinate systems?
supports_distance_geodetic = True
supports_length_geodetic = True
supports_perimeter_geodetic = False
supports_area_geodetic = True
# Is the database able to count vertices on polygons (with `num_points`)?
supports_num_points_poly = True
# Does the backend support expressions for specifying distance in the
# dwithin lookup?
supports_dwithin_distance_expr = True
# Does the database have raster support?
supports_raster = False
# Does the database support a unique index on geometry fields?
supports_geometry_field_unique_index = True
# Can SchemaEditor alter geometry fields?
can_alter_geometry_field = True
# Do the database functions/aggregates support the tolerance parameter?
supports_tolerance_parameter = False
# Set of options that AsGeoJSON() doesn't support.
unsupported_geojson_options = {}
# Does Intersection() return None (rather than an empty GeometryCollection)
# for empty results?
empty_intersection_returns_none = True
@property
def supports_bbcontains_lookup(self):
return 'bbcontains' in self.connection.ops.gis_operators
@property
def supports_contained_lookup(self):
return 'contained' in self.connection.ops.gis_operators
@property
def supports_crosses_lookup(self):
return 'crosses' in self.connection.ops.gis_operators
@property
def supports_distances_lookups(self):
return self.has_Distance_function
@property
def supports_dwithin_lookup(self):
return 'dwithin' in self.connection.ops.gis_operators
@property
def supports_relate_lookup(self):
return 'relate' in self.connection.ops.gis_operators
@property
def supports_isvalid_lookup(self):
return self.has_IsValid_function
# Is the aggregate supported by the database?
@property
def supports_collect_aggr(self):
return models.Collect not in self.connection.ops.disallowed_aggregates
@property
def supports_extent_aggr(self):
return models.Extent not in self.connection.ops.disallowed_aggregates
@property
def supports_make_line_aggr(self):
return models.MakeLine not in self.connection.ops.disallowed_aggregates
@property
def supports_union_aggr(self):
return models.Union not in self.connection.ops.disallowed_aggregates
def __getattr__(self, name):
m = re.match(r'has_(\w*)_function$', name)
if m:
func_name = m[1]
return func_name not in self.connection.ops.unsupported_functions
raise AttributeError

View File

@@ -0,0 +1,136 @@
from django.contrib.gis import gdal
class SpatialRefSysMixin:
"""
The SpatialRefSysMixin is a class used by the database-dependent
SpatialRefSys objects to reduce redundant code.
"""
@property
def srs(self):
"""
Return a GDAL SpatialReference object.
"""
# TODO: Is caching really necessary here? Is complexity worth it?
if hasattr(self, '_srs'):
# Returning a clone of the cached SpatialReference object.
return self._srs.clone()
else:
# Attempting to cache a SpatialReference object.
# Trying to get from WKT first.
try:
self._srs = gdal.SpatialReference(self.wkt)
return self.srs
except Exception as e:
msg = e
try:
self._srs = gdal.SpatialReference(self.proj4text)
return self.srs
except Exception as e:
msg = e
raise Exception('Could not get OSR SpatialReference from WKT: %s\nError:\n%s' % (self.wkt, msg))
@property
def ellipsoid(self):
"""
Return a tuple of the ellipsoid parameters:
(semimajor axis, semiminor axis, and inverse flattening).
"""
return self.srs.ellipsoid
@property
def name(self):
"Return the projection name."
return self.srs.name
@property
def spheroid(self):
"Return the spheroid name for this spatial reference."
return self.srs['spheroid']
@property
def datum(self):
"Return the datum for this spatial reference."
return self.srs['datum']
@property
def projected(self):
"Is this Spatial Reference projected?"
return self.srs.projected
@property
def local(self):
"Is this Spatial Reference local?"
return self.srs.local
@property
def geographic(self):
"Is this Spatial Reference geographic?"
return self.srs.geographic
@property
def linear_name(self):
"Return the linear units name."
return self.srs.linear_name
@property
def linear_units(self):
"Return the linear units."
return self.srs.linear_units
@property
def angular_name(self):
"Return the name of the angular units."
return self.srs.angular_name
@property
def angular_units(self):
"Return the angular units."
return self.srs.angular_units
@property
def units(self):
"Return a tuple of the units and the name."
if self.projected or self.local:
return (self.linear_units, self.linear_name)
elif self.geographic:
return (self.angular_units, self.angular_name)
else:
return (None, None)
@classmethod
def get_units(cls, wkt):
"""
Return a tuple of (unit_value, unit_name) for the given WKT without
using any of the database fields.
"""
return gdal.SpatialReference(wkt).units
@classmethod
def get_spheroid(cls, wkt, string=True):
"""
Class method used by GeometryField on initialization to
retrieve the `SPHEROID[..]` parameters from the given WKT.
"""
srs = gdal.SpatialReference(wkt)
sphere_params = srs.ellipsoid
sphere_name = srs['spheroid']
if not string:
return sphere_name, sphere_params
else:
# `string` parameter used to place in format acceptable by PostGIS
if len(sphere_params) == 3:
radius, flattening = sphere_params[0], sphere_params[2]
else:
radius, flattening = sphere_params
return 'SPHEROID["%s",%s,%s]' % (sphere_name, radius, flattening)
def __str__(self):
"""
Return the string representation, a 'pretty' OGC WKT.
"""
return str(self.srs)

View File

@@ -0,0 +1,159 @@
from django.contrib.gis.db.models import GeometryField
from django.contrib.gis.db.models.functions import Distance
from django.contrib.gis.measure import (
Area as AreaMeasure, Distance as DistanceMeasure,
)
from django.db import NotSupportedError
from django.utils.functional import cached_property
class BaseSpatialOperations:
# Quick booleans for the type of this spatial backend, and
# an attribute for the spatial database version tuple (if applicable)
postgis = False
spatialite = False
mariadb = False
mysql = False
oracle = False
spatial_version = None
# How the geometry column should be selected.
select = '%s'
@cached_property
def select_extent(self):
return self.select
# Aggregates
disallowed_aggregates = ()
geom_func_prefix = ''
# Mapping between Django function names and backend names, when names do not
# match; used in spatial_function_name().
function_names = {}
# Set of known unsupported functions of the backend
unsupported_functions = {
'Area', 'AsGeoJSON', 'AsGML', 'AsKML', 'AsSVG', 'Azimuth',
'BoundingCircle', 'Centroid', 'Difference', 'Distance', 'Envelope',
'GeoHash', 'GeometryDistance', 'Intersection', 'IsValid', 'Length',
'LineLocatePoint', 'MakeValid', 'MemSize', 'NumGeometries',
'NumPoints', 'Perimeter', 'PointOnSurface', 'Reverse', 'Scale',
'SnapToGrid', 'SymDifference', 'Transform', 'Translate', 'Union',
}
# Constructors
from_text = False
# Default conversion functions for aggregates; will be overridden if implemented
# for the spatial backend.
def convert_extent(self, box, srid):
raise NotImplementedError('Aggregate extent not implemented for this spatial backend.')
def convert_extent3d(self, box, srid):
raise NotImplementedError('Aggregate 3D extent not implemented for this spatial backend.')
# For quoting column values, rather than columns.
def geo_quote_name(self, name):
return "'%s'" % name
# GeometryField operations
def geo_db_type(self, f):
"""
Return the database column type for the geometry field on
the spatial backend.
"""
raise NotImplementedError('subclasses of BaseSpatialOperations must provide a geo_db_type() method')
def get_distance(self, f, value, lookup_type):
"""
Return the distance parameters for the given geometry field,
lookup value, and lookup type.
"""
raise NotImplementedError('Distance operations not available on this spatial backend.')
def get_geom_placeholder(self, f, value, compiler):
"""
Return the placeholder for the given geometry field with the given
value. Depending on the spatial backend, the placeholder may contain a
stored procedure call to the transformation function of the spatial
backend.
"""
def transform_value(value, field):
return value is not None and value.srid != field.srid
if hasattr(value, 'as_sql'):
return (
'%s(%%s, %s)' % (self.spatial_function_name('Transform'), f.srid)
if transform_value(value.output_field, f)
else '%s'
)
if transform_value(value, f):
# Add Transform() to the SQL placeholder.
return '%s(%s(%%s,%s), %s)' % (
self.spatial_function_name('Transform'),
self.from_text, value.srid, f.srid,
)
elif self.connection.features.has_spatialrefsys_table:
return '%s(%%s,%s)' % (self.from_text, f.srid)
else:
# For backwards compatibility on MySQL (#27464).
return '%s(%%s)' % self.from_text
def check_expression_support(self, expression):
if isinstance(expression, self.disallowed_aggregates):
raise NotSupportedError(
"%s spatial aggregation is not supported by this database backend." % expression.name
)
super().check_expression_support(expression)
def spatial_aggregate_name(self, agg_name):
raise NotImplementedError('Aggregate support not implemented for this spatial backend.')
def spatial_function_name(self, func_name):
if func_name in self.unsupported_functions:
raise NotSupportedError("This backend doesn't support the %s function." % func_name)
return self.function_names.get(func_name, self.geom_func_prefix + func_name)
# Routines for getting the OGC-compliant models.
def geometry_columns(self):
raise NotImplementedError('Subclasses of BaseSpatialOperations must provide a geometry_columns() method.')
def spatial_ref_sys(self):
raise NotImplementedError('subclasses of BaseSpatialOperations must a provide spatial_ref_sys() method')
distance_expr_for_lookup = staticmethod(Distance)
def get_db_converters(self, expression):
converters = super().get_db_converters(expression)
if isinstance(expression.output_field, GeometryField):
converters.append(self.get_geometry_converter(expression))
return converters
def get_geometry_converter(self, expression):
raise NotImplementedError(
'Subclasses of BaseSpatialOperations must provide a '
'get_geometry_converter() method.'
)
def get_area_att_for_field(self, field):
if field.geodetic(self.connection):
if self.connection.features.supports_area_geodetic:
return 'sq_m'
raise NotImplementedError('Area on geodetic coordinate systems not supported.')
else:
units_name = field.units_name(self.connection)
if units_name:
return AreaMeasure.unit_attname(units_name)
def get_distance_att_for_field(self, field):
dist_att = None
if field.geodetic(self.connection):
if self.connection.features.supports_distance_geodetic:
dist_att = 'm'
else:
units = field.units_name(self.connection)
if units:
dist_att = DistanceMeasure.unit_attname(units)
return dist_att