diff --git a/django/contrib/gis/db/backends/spatialite/base.py b/django/contrib/gis/db/backends/spatialite/base.py
a
|
b
|
|
2 | 2 | from django.conf import settings |
3 | 3 | |
4 | 4 | from django.core.exceptions import ImproperlyConfigured |
5 | | from django.db.backends.sqlite3.base import * |
6 | 5 | from django.db.backends.sqlite3.base import ( |
7 | | _sqlite_extract, _sqlite_date_trunc, _sqlite_regexp, |
8 | | DatabaseWrapper as SqliteDatabaseWrapper) |
| 6 | _sqlite_extract, _sqlite_date_trunc, _sqlite_regexp, _sqlite_format_dtdelta, |
| 7 | connection_created, Database, DatabaseWrapper as SQLiteDatabaseWrapper, |
| 8 | SQLiteCursorWrapper) |
9 | 9 | from django.contrib.gis.db.backends.spatialite.client import SpatiaLiteClient |
10 | 10 | from django.contrib.gis.db.backends.spatialite.creation import SpatiaLiteCreation |
11 | 11 | from django.contrib.gis.db.backends.spatialite.introspection import SpatiaLiteIntrospection |
12 | 12 | from django.contrib.gis.db.backends.spatialite.operations import SpatiaLiteOperations |
13 | 13 | |
14 | | class DatabaseWrapper(SqliteDatabaseWrapper): |
| 14 | class DatabaseWrapper(SQLiteDatabaseWrapper): |
15 | 15 | def __init__(self, *args, **kwargs): |
16 | 16 | # Before we get too far, make sure pysqlite 2.5+ is installed. |
17 | 17 | if Database.version_info < (2, 5, 0): |
… |
… |
|
52 | 52 | self.connection.create_function("django_extract", 2, _sqlite_extract) |
53 | 53 | self.connection.create_function("django_date_trunc", 2, _sqlite_date_trunc) |
54 | 54 | self.connection.create_function("regexp", 2, _sqlite_regexp) |
| 55 | self.connection.create_function("django_format_dtdelta", 5, _sqlite_format_dtdelta) |
55 | 56 | connection_created.send(sender=self.__class__, connection=self) |
56 | 57 | |
57 | 58 | ## From here on, customized for GeoDjango ## |
diff --git a/django/contrib/gis/db/backends/spatialite/compiler.py b/django/contrib/gis/db/backends/spatialite/compiler.py
new file mode 100644
-
|
+
|
|
| 1 | from django.db.backends.util import typecast_timestamp |
| 2 | from django.db.models.sql import compiler |
| 3 | from django.db.models.sql.constants import MULTI |
| 4 | from django.contrib.gis.db.models.sql.compiler import GeoSQLCompiler as BaseGeoSQLCompiler |
| 5 | |
| 6 | SQLCompiler = compiler.SQLCompiler |
| 7 | |
| 8 | class GeoSQLCompiler(BaseGeoSQLCompiler, SQLCompiler): |
| 9 | pass |
| 10 | |
| 11 | class SQLInsertCompiler(compiler.SQLInsertCompiler, GeoSQLCompiler): |
| 12 | pass |
| 13 | |
| 14 | class SQLDeleteCompiler(compiler.SQLDeleteCompiler, GeoSQLCompiler): |
| 15 | pass |
| 16 | |
| 17 | class SQLUpdateCompiler(compiler.SQLUpdateCompiler, GeoSQLCompiler): |
| 18 | pass |
| 19 | |
| 20 | class SQLAggregateCompiler(compiler.SQLAggregateCompiler, GeoSQLCompiler): |
| 21 | pass |
| 22 | |
| 23 | class SQLDateCompiler(compiler.SQLDateCompiler, GeoSQLCompiler): |
| 24 | """ |
| 25 | This is overridden for GeoDjango to properly cast date columns when |
| 26 | using SpatiaLite. |
| 27 | """ |
| 28 | def results_iter(self): |
| 29 | offset = len(self.query.extra_select) |
| 30 | for rows in self.execute_sql(MULTI): |
| 31 | for row in rows: |
| 32 | date = typecast_timestamp(row[offset]) |
| 33 | yield date |
diff --git a/django/contrib/gis/db/backends/spatialite/operations.py b/django/contrib/gis/db/backends/spatialite/operations.py
a
|
b
|
|
48 | 48 | return (SpatiaLiteDistance(operator),) |
49 | 49 | |
50 | 50 | class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations): |
51 | | compiler_module = 'django.contrib.gis.db.models.sql.compiler' |
| 51 | compiler_module = 'django.contrib.gis.db.backends.spatialite.compiler' |
52 | 52 | name = 'spatialite' |
53 | 53 | spatialite = True |
54 | 54 | version_regex = re.compile(r'^(?P<major>\d)\.(?P<minor1>\d)\.(?P<minor2>\d+)') |
diff --git a/django/contrib/gis/tests/geoapp/models.py b/django/contrib/gis/tests/geoapp/models.py
a
|
b
|
|
19 | 19 | # This is an inherited model from City |
20 | 20 | class PennsylvaniaCity(City): |
21 | 21 | county = models.CharField(max_length=30) |
| 22 | founded = models.DateTimeField() |
22 | 23 | objects = models.GeoManager() # TODO: This should be implicitly inherited. |
23 | 24 | |
24 | 25 | class State(models.Model): |
diff --git a/django/contrib/gis/tests/geoapp/test_regress.py b/django/contrib/gis/tests/geoapp/test_regress.py
a
|
b
|
|
1 | | import unittest |
| 1 | from datetime import datetime |
2 | 2 | from django.contrib.gis.tests.utils import no_mysql, no_spatialite |
3 | 3 | from django.contrib.gis.shortcuts import render_to_kmz |
4 | | from models import City |
| 4 | from django.test import TestCase |
| 5 | from models import City, PennsylvaniaCity |
5 | 6 | |
6 | | class GeoRegressionTests(unittest.TestCase): |
| 7 | class GeoRegressionTests(TestCase): |
7 | 8 | |
8 | 9 | def test01_update(self): |
9 | 10 | "Testing GeoQuerySet.update(), see #10411." |
… |
… |
|
35 | 36 | extent = City.objects.filter(name='Pueblo').extent() |
36 | 37 | for ref_val, val in zip(ref_ext, extent): |
37 | 38 | self.assertAlmostEqual(ref_val, val, 4) |
| 39 | |
| 40 | def test04_unicode_date(self): |
| 41 | "Testing dates are converted properly, even on SpatiaLite, see #16757." |
| 42 | founded = datetime(1857, 5, 23) |
| 43 | mansfield = PennsylvaniaCity.objects.create(name='Mansfield', county='Tioga', point='POINT(-77.071445 41.823881)', |
| 44 | founded=founded) |
| 45 | self.assertEqual(founded, PennsylvaniaCity.objects.dates('founded', 'day')[0]) |
diff --git a/django/contrib/gis/tests/geoapp/tests.py b/django/contrib/gis/tests/geoapp/tests.py
a
|
b
|
|
1 | 1 | import re |
| 2 | from datetime import datetime |
2 | 3 | from django.db import connection |
3 | 4 | from django.contrib.gis import gdal |
4 | 5 | from django.contrib.gis.geos import (fromstr, GEOSGeometry, |
… |
… |
|
639 | 640 | def test26_inherited_geofields(self): |
640 | 641 | "Test GeoQuerySet methods on inherited Geometry fields." |
641 | 642 | # Creating a Pennsylvanian city. |
642 | | mansfield = PennsylvaniaCity.objects.create(name='Mansfield', county='Tioga', point='POINT(-77.071445 41.823881)') |
| 643 | mansfield = PennsylvaniaCity.objects.create(name='Mansfield', county='Tioga', point='POINT(-77.071445 41.823881)', |
| 644 | founded=datetime(1857, 5, 23)) |
643 | 645 | |
644 | 646 | # All transformation SQL will need to be performed on the |
645 | 647 | # _parent_ table. |