django.core.exceptions.ImproperlyConfigured: SpatiaLite requires SQLite to be configured to allow extension loading

后端 未结 1 401
孤城傲影
孤城傲影 2021-01-13 16:13

I installed spatialite for Django project but when I try to migrate it show me this error :

File \"/Library/Frameworks/Python.frame         


        
相关标签:
1条回答
  • 2021-01-13 16:45

    The Issue

    The ImproperlyConfigured error is raised in django.contrib.gis.db.backends.spatialite.base when using a Python build based on the default sqlite3 library - which is the case for MacOSX and probably most Linux distros - which was built with extension loading disabled. So, this won't work:

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

    Following the directions of the GeoDjango won't solve the problem in most cases. Even installing the spatialite-tools via Homebrew only installs new spatialite and sqlite executables and libraries in the Homebrew directory.

    The Solution

    Assuming sqlite and spatialite are installed (e.g. via Homebrew) and the respective sqlite version has load_extention enabled, you can build Python from scratch with this sqlite library linked. It's pretty easy using pyenv. Specific build options can be provided via the PYTHON_CONFIGURE_OPTS environment variable (details here) and setting CPPFLAGS and LDFLAGS (see here)

    Building with pyenv assuming sqlite was installed via homebrew (check which sqlite3and brew info sqlite for details on which versions are installed and where):

    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
    

    If dependencies are missing (e.g. openssl), see below on building Python manually.

    Finally, it's important to reference the dynamically linked spatialite in your Django settings (so make sure /usr/local/lib/mod_spatialite.dylib exists)

    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'),
        }
    }
    

    Build SQLite and Python manually

    To compile sqlite from source with load extensions enabled (see docs), download the amalgamated source file from the website and follow the instructions. You'll want to include the build option -DSQLITE_ENABLE_RTREE but NOT -DSQLITE_OMIT_LOAD_EXTENSION!

    Once sqlite3 compiled, run the executable and check via the command .dbconfig

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

    Loading extensions is turned off by default, to avoid security issues.

    Building Python manually is also pretty straightforward and follows a similar pattern as installing via pyenv. Once dependencies are met (e.g. on macos brew install openssl xz gdbm), you download the tarball with the desired version and set the compile options to enable sqlite extension loading (and telling make where to find your newly compiled SQLite build):

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

    Other solutions (and other systems)

    The described solution applied to MacOS primarily and Python3, since sqlite3 ships as part of the standard python library for Python3, as opposed to a seprate package for Python 2. Previous solutions, such as [pysqlite] only work for Python2 which is EOL.

    What you tried may have been based on an older solution, which may have applied to Python2.

    Also, there seemed to have been proposed other solutions for Windows using cyqlite

    0 讨论(0)
提交回复
热议问题