GeoDjango с ошибкой Docker: объект 'DatabaseOperations' не имеет атрибута 'geo_db_type'
Похоже, это распространенная ошибка, и я проверил все решения, которые смог найти (их всего около 4, и почти все они связаны с неправильной конфигурацией). Я НЕ использую heroku, но я использую docker. Я использую образы docker python:3.9.7
и postgis/postgis:10-3.1-alpine
.
Мой Dockerfile содержит следующую строку:
ARG BUILD_ENV=production
# ...
FROM python:3.9.7 as apiserver
#...
RUN apt-get update && \
apt-get install --no-install-recommends -y apt-utils build-essential sudo git wget curl ca-certificates nginx openssl libpq-dev expect libmagic-dev graphviz python3-gdal python3-pandas postgis binutils libproj-dev gdal-bin python3-djangorestframework-gis
# ...
RUN pip install --upgrade pip && pip install -r requirements/${BUILD_ENV}.txt
# ...
Это должно убедиться, что все зависимости, необходимые мне для сборки либ postgis для django, присутствуют, так что когда я запущу pip install, у него будет все необходимое. Он более многословен, чем нужно, потому что в документации по GeoDjango сказано установить postgis binutils libproj-dev gdal-bin
, а в drf-gis
есть все библиотеки GeoDjango в качестве зависимостей. Я планирую использовать пакет drf-gis, но в настоящее время не использую его.
requirements/production.txt
django-cors-headers==3.5.0
django-extensions==3.0.9
django-filter==2.4.0
# ...
Django==3.1.13
# ...
djangorestframework==3.12.4
djangorestframework-gis==0.17
# ...
Я включил правильное приложение в INSTALLED_APPS:
INSTALLED_APPS = [
'django.contrib.contenttypes',
'django.contrib.admin',
'django.contrib.admindocs',
'django.contrib.auth',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.gis',
'django_extensions',
'rest_framework',
'rest_framework.authtoken',
# 'rest_framework_gis',
'django.contrib.sites',
'django_filters',
'apiserver', # api v1 app doesn't use geodjango
'apiserver_v2', # api v2 uses geodjango
# ...
]
Я также установил следующее в качестве конфигурации моей БД:
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'HOST': os.environ.get('PGHOST'),
'PORT': 5432,
'NAME': os.environ.get('PGDATABASE'),
'USER': os.environ.get('PGUSER'),
'PASSWORD': os.environ.get('PGPASSWORD'),
'CONN_MAX_AGE': os.environ.get('DB_CONN_MAX_AGE', 500),
},
}
У меня также есть следующая миграция в качестве первой миграции в моем приложении. Мне это не понадобилось в моем тестировании со SpatiaLite, но я добавил это здесь, чтобы быть полным в документации.
0000_postgis.py
from django.contrib.postgres.operations import CreateExtension
from django.db import migrations
class Migration(migrations.Migration):
operations = [
CreateExtension('postgis'),
CreateExtension('postgis_raster'),
]
Эта миграция работает, как ожидалось, и расширение, похоже, установлено:
apiserver_db_name=# \dx
Список установленных расширений
Имя | Версия | Схема | Описание
.
----------------+---------+------------+------------------------------------------------------------
plpgsql | 1.0 | pg_catalog | процедурный язык PL/pgSQL
postgis | 3.1.4 | public | PostGIS геометрия и география пространственные типы и функции
postgis_raster | 3.1.4 | public | PostGIS растровые типы и функции
(3 строки)
Теперь все настроено в соответствии с документацией. Однако, когда я запускаю миграции, я получаю следующую ошибку:
SPECIAL NOTE: Я просмотрел все проблемы, которые я мог найти, которые генерируют эту ошибку, но я не могу найти никакого объяснения, что эта ошибка на самом деле означает. Почему он ищет этот атрибут и как я могу проверить, что он есть? Какой пакет должен его туда поместить и как? Если бы я мог это выяснить, диагностика и устранение этой проблемы были бы намного проще.
Решено! Это произошло из-за того, что другая конфигурация переопределила настройки БД. Я был очень категоричен, что это не проблема конфигурации, и мне жаль. Я проверил это, запустив оболочку администратора в запущенном приложении django и проверив settings.DATABASES
. (Другим переопределением было django-prometheus, если вам интересно)