django.core.exceptions.ImproperlyConfigured: SpatiaLite требует, чтобы SQLite был настроен для разрешения загрузки расширения

Я установил spatialite за Django проект, но когда я пытаюсь перенести, он показывает мне эту ошибку:

File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django/contrib/gis/db/backends/spatialite/base.py", line 44, in get_new_connection
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: SpatiaLite requires SQLite to be configured to allow extension loading.

Не знаю, как вычислить. Я попробовал это, изменив файл libexec/setuptools/setup.cfg

[build_ext]
 #define=
include_dirs=/Library/Frameworks/SQLite3.framework/unix/include
library_dirs=/Library/Frameworks/SQLite3.framework/unix/lib
libraries=sqlite3
#define=SQLITE_OMIT_LOAD_EXTENSION

Я установил Spaceite by brew, затем изменил settings.py следующим образом:

DATABASES = {
 'default': {
    'ENGINE': 'django.contrib.gis.db.backends.spatialite',
    'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
 }
}
SPATIALITE_LIBRARY_PATH='/usr/local/lib/mod_spatialite.dylib'

1 ответ

Проблема

В ImproperlyConfigured ошибка возникает в django.contrib.gis.db.backends.spatialite.baseпри использовании сборки Python на основе библиотеки sqlite3 по умолчанию - что имеет место для MacOSX и, вероятно, большинства дистрибутивов Linux - которая была построена с отключенной загрузкой расширений. Итак, это не сработает:

conn.enable_load_extension(True)
conn.load_extension(SPATIALITE_LIBRARY_PATH)

Следование указаниям GeoDjango в большинстве случаев не решит проблему. Даже установкаspatialite-toolsчерез Homebrew устанавливает только новые исполняемые файлы и библиотеки Spaceite и sqlite в каталог Homebrew.

Решение

Предполагая, что sqlite и spaceite установлены (например, через Homebrew), а соответствующая версия sqlite имеет load_extentionвключен, вы можете создать Python с нуля с помощью этой связанной библиотеки sqlite. Использовать pyenv довольно просто. Конкретные параметры сборки могут быть предоставлены черезPYTHON_CONFIGURE_OPTSпеременная среды (подробности здесь) и настройкаCPPFLAGS а также LDFLAGS(см. здесь)

Сборка с pyenv при условии, что sqlite был установлен с помощью homebrew (проверьте which sqlite3а также brew info sqlite для получения подробной информации о том, какие версии установлены и где):

PYTHON_CONFIGURE_OPTS="--enable-loadable-sqlite-extensions --enable-optimizations --with-openssl=\$(brew --prefix openssl)" \
LDFLAGS="-L/usr/local/opt/sqlite/lib" \
CPPFLAGS="-I/usr/local/opt/sqlite/include" \
pyenv install 3.8.2

Если зависимости отсутствуют (например, openssl), см. Ниже о создании Python вручную.

Наконец, важно указать динамически связанный пространственный объект в настройках Django (поэтому убедитесь, что /usr/local/lib/mod_spatialite.dylib существует)

SPATIALITE_LIBRARY_PATH = '/usr/local/lib/mod_spatialite.dylib'
DATABASES = {
    'default': {
        'ENGINE': 'django.contrib.gis.db.backends.spatialite',
        'NAME': os.path.join(BASE_DIR, 'db.spatialite3'),
    }
}

Собирайте SQLite и Python вручную

Чтобы скомпилировать sqlite из исходного кода с включенными расширениями загрузки ( см. Документацию), загрузите объединенный исходный файл с веб-сайта и следуйте инструкциям. Вы захотите включить опцию сборки-DSQLITE_ENABLE_RTREEно НЕ -DSQLITE_OMIT_LOAD_EXTENSION!

После компиляции sqlite3 запустите исполняемый файл и проверьте с помощью команды .dbconfig

sqlite > .dbconfig
[...]
load_extension on
[...]

По умолчанию загрузка расширений отключена, чтобы избежать проблем с безопасностью.

Сборка Python вручную также довольно проста и выполняется по той же схеме, что и установка через pyenv. Как только зависимости соблюдены (например, на macos brew install openssl xz gdbm), вы загружаете tarball с нужной версией и устанавливаете параметры компиляции, чтобы включить загрузку расширения sqlite (и сообщить программе make, где найти вашу недавно скомпилированную сборку SQLite):

./configure --enable-loadable-sqlite-extensions --enable-optimizations --with-openssl=$(brew --prefix openssl)
LDFLAGS="-L<path-to-sqlite>" \
CPPFLAGS="-I<path-to-sqlite>" \
make -j2

Другие решения (и другие системы)

Описанное решение применялось в первую очередь к MacOS и Python3, поскольку sqlite3 поставляется как часть стандартной библиотеки python для Python3, в отличие от отдельного пакета для Python 2. Предыдущие решения, такие как [pysqlite], работают только для Python2, который является EOL.

То, что вы пробовали, могло быть основано на более старом решении, которое могло применяться к Python2.

Кроме того, похоже, были предложены другие решения для Windows с использованиемcyqlite

Другие вопросы по тегам