Fixed #20968 -- Checked Spatialite metadata before migrations
Thanks Kenial S. Lee for the initial patch and Tim Graham for the review.
This commit is contained in:
parent
1aa41dd000
commit
8f97413fae
|
@ -79,3 +79,12 @@ class DatabaseWrapper(SQLiteDatabaseWrapper):
|
||||||
six.reraise(ImproperlyConfigured, ImproperlyConfigured(new_msg), sys.exc_info()[2])
|
six.reraise(ImproperlyConfigured, ImproperlyConfigured(new_msg), sys.exc_info()[2])
|
||||||
cur.close()
|
cur.close()
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
|
def prepare_database(self):
|
||||||
|
super(DatabaseWrapper, self).prepare_database()
|
||||||
|
# Check if spatial metadata have been initialized in the database
|
||||||
|
with self.cursor() as cursor:
|
||||||
|
cursor.execute("PRAGMA table_info(geometry_columns);")
|
||||||
|
if cursor.fetchall() == []:
|
||||||
|
arg = "1" if self.features.supports_initspatialmetadata_in_one_transaction else ""
|
||||||
|
cursor.execute("SELECT InitSpatialMetaData(%s)" % arg)
|
||||||
|
|
|
@ -30,11 +30,3 @@ class SpatiaLiteCreation(DatabaseCreation):
|
||||||
style.SQL_FIELD(gqn(f.column)) + ');')
|
style.SQL_FIELD(gqn(f.column)) + ');')
|
||||||
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def _create_test_db_pre_migrate_sql(self):
|
|
||||||
"""
|
|
||||||
Creates the spatial metadata tables.
|
|
||||||
"""
|
|
||||||
cur = self.connection._cursor()
|
|
||||||
arg = "1" if self.connection.features.supports_initspatialmetadata_in_one_transaction else ""
|
|
||||||
cur.execute("SELECT InitSpatialMetaData(%s)" % arg)
|
|
||||||
|
|
|
@ -64,6 +64,8 @@ class Command(BaseCommand):
|
||||||
if options.get("list", False):
|
if options.get("list", False):
|
||||||
return self.show_migration_list(connection, [options['app_label']] if options['app_label'] else None)
|
return self.show_migration_list(connection, [options['app_label']] if options['app_label'] else None)
|
||||||
|
|
||||||
|
# Hook for backends needing any database preparation
|
||||||
|
connection.prepare_database()
|
||||||
# Work out which apps have migrations and which do not
|
# Work out which apps have migrations and which do not
|
||||||
executor = MigrationExecutor(connection, self.migration_progress_callback)
|
executor = MigrationExecutor(connection, self.migration_progress_callback)
|
||||||
|
|
||||||
|
|
|
@ -432,6 +432,13 @@ class BaseDatabaseWrapper(object):
|
||||||
|
|
||||||
##### Miscellaneous #####
|
##### Miscellaneous #####
|
||||||
|
|
||||||
|
def prepare_database(self):
|
||||||
|
"""
|
||||||
|
Hook to do any database check or preparation, generally called before
|
||||||
|
migrating a project or an app.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def wrap_database_errors(self):
|
def wrap_database_errors(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -371,8 +371,6 @@ class BaseDatabaseCreation(object):
|
||||||
settings.DATABASES[self.connection.alias]["NAME"] = test_database_name
|
settings.DATABASES[self.connection.alias]["NAME"] = test_database_name
|
||||||
self.connection.settings_dict["NAME"] = test_database_name
|
self.connection.settings_dict["NAME"] = test_database_name
|
||||||
|
|
||||||
self._create_test_db_pre_migrate_sql()
|
|
||||||
|
|
||||||
# We report migrate messages at one level lower than that requested.
|
# We report migrate messages at one level lower than that requested.
|
||||||
# This ensures we don't get flooded with messages during testing
|
# This ensures we don't get flooded with messages during testing
|
||||||
# (unless you really ask to be flooded).
|
# (unless you really ask to be flooded).
|
||||||
|
@ -398,12 +396,6 @@ class BaseDatabaseCreation(object):
|
||||||
|
|
||||||
return test_database_name
|
return test_database_name
|
||||||
|
|
||||||
def _create_test_db_pre_migrate_sql(self):
|
|
||||||
"""
|
|
||||||
Hook for databases to load SQL before creating the test DB.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def serialize_db_to_string(self):
|
def serialize_db_to_string(self):
|
||||||
"""
|
"""
|
||||||
Serializes all data in the database into a JSON string.
|
Serializes all data in the database into a JSON string.
|
||||||
|
|
|
@ -211,34 +211,11 @@ following to your ``settings.py``::
|
||||||
Creating a spatial database for SpatiaLite
|
Creating a spatial database for SpatiaLite
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
After you've installed SpatiaLite, you'll need to create a number of spatial
|
When running ``manage.py migrate`` with a SQLite or SpatiaLite database, the
|
||||||
metadata tables in your database in order to perform spatial queries.
|
database file will be automatically created if it doesn't exist. Django will
|
||||||
|
also ensure that the spatial metadata are initialized in the database.
|
||||||
|
|
||||||
Use the ``spatialite`` utility to call the ``InitSpatialMetaData()`` function,
|
.. versionchanged:: 1.8
|
||||||
like this::
|
|
||||||
|
|
||||||
$ spatialite geodjango.db "SELECT InitSpatialMetaData();"
|
Prior to Django 1.8, you had to intialize spatial metadata tables yourself
|
||||||
the SPATIAL_REF_SYS table already contains some row(s)
|
by manually running the "SELECT InitSpatialMetaData();" query.
|
||||||
InitSpatiaMetaData ()error:"table spatial_ref_sys already exists"
|
|
||||||
0
|
|
||||||
|
|
||||||
You can safely ignore the error messages shown.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
The parameter ``geodjango.db`` is the *filename* of the SQLite database
|
|
||||||
you want to use. Use the same in the :setting:`DATABASES` ``"name"`` key
|
|
||||||
inside your ``settings.py``.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
When running ``manage.py migrate`` with a SQLite (or SpatiaLite) database,
|
|
||||||
the database file will be automatically created if it doesn't exist. In
|
|
||||||
this case, if your models contain any geometry columns, you'll see this
|
|
||||||
error::
|
|
||||||
|
|
||||||
CreateSpatialIndex() error: "no such table: geometry_columns"
|
|
||||||
|
|
||||||
It's because the table creation queries are executed without spatial
|
|
||||||
metadata tables. To avoid this, make the database file before executing
|
|
||||||
``manage.py migrate`` as described above.
|
|
||||||
|
|
Loading…
Reference in New Issue