File: introspection.py

package info (click to toggle)
python-django 1%3A1.11.29-1~deb10u1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 47,428 kB
  • sloc: python: 220,776; javascript: 13,523; makefile: 209; xml: 201; sh: 64
file content (78 lines) | stat: -rw-r--r-- 3,254 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
from django.contrib.gis.gdal import OGRGeomType
from django.db.backends.sqlite3.introspection import (
    DatabaseIntrospection, FlexibleFieldLookupDict,
)
from django.utils import six


class GeoFlexibleFieldLookupDict(FlexibleFieldLookupDict):
    """
    Sublcass that includes updates the `base_data_types_reverse` dict
    for geometry field types.
    """
    base_data_types_reverse = FlexibleFieldLookupDict.base_data_types_reverse.copy()
    base_data_types_reverse.update(
        {'point': 'GeometryField',
         'linestring': 'GeometryField',
         'polygon': 'GeometryField',
         'multipoint': 'GeometryField',
         'multilinestring': 'GeometryField',
         'multipolygon': 'GeometryField',
         'geometrycollection': 'GeometryField',
         })


class SpatiaLiteIntrospection(DatabaseIntrospection):
    data_types_reverse = GeoFlexibleFieldLookupDict()

    def get_geometry_type(self, table_name, geo_col):
        cursor = self.connection.cursor()
        try:
            # Querying the `geometry_columns` table to get additional metadata.
            cursor.execute('SELECT coord_dimension, srid, geometry_type '
                           'FROM geometry_columns '
                           'WHERE f_table_name=%s AND f_geometry_column=%s',
                           (table_name, geo_col))
            row = cursor.fetchone()
            if not row:
                raise Exception('Could not find a geometry column for "%s"."%s"' %
                                (table_name, geo_col))

            # OGRGeomType does not require GDAL and makes it easy to convert
            # from OGC geom type name to Django field.
            ogr_type = row[2]
            if isinstance(ogr_type, six.integer_types) and ogr_type > 1000:
                # SpatiaLite versions >= 4 use the new SFSQL 1.2 offsets
                # 1000 (Z), 2000 (M), and 3000 (ZM) to indicate the presence of
                # higher dimensional coordinates (M not yet supported by Django).
                ogr_type = ogr_type % 1000 + OGRGeomType.wkb25bit
            field_type = OGRGeomType(ogr_type).django

            # Getting any GeometryField keyword arguments that are not the default.
            dim = row[0]
            srid = row[1]
            field_params = {}
            if srid != 4326:
                field_params['srid'] = srid
            if (isinstance(dim, six.string_types) and 'Z' in dim) or dim == 3:
                field_params['dim'] = 3
        finally:
            cursor.close()

        return field_type, field_params

    def get_constraints(self, cursor, table_name):
        constraints = super(SpatiaLiteIntrospection, self).get_constraints(cursor, table_name)
        cursor.execute('SELECT f_geometry_column '
                       'FROM geometry_columns '
                       'WHERE f_table_name=%s AND spatial_index_enabled=1', (table_name,))
        for row in cursor.fetchall():
            constraints['%s__spatial__index' % row[0]] = {
                "columns": [row[0]],
                "primary_key": False,
                "unique": False,
                "foreign_key": None,
                "check": False,
                "index": True,
            }
        return constraints