【发布时间】:2018-04-14 04:13:46
【问题描述】:
背景
我将 Django 与多个数据库一起使用:我有一个 Postgres 数据库和一个 mysql 数据库(充满了我正在慢慢转换为 Postgres 的遗留数据)。
我最近引入了 GeoDjango(以 django.contrib.gis 的形式),带有用于存储 lat/lng 信息的 postgis 扩展。应用程序本身似乎运行良好。我可以很好地访问 mysql 数据库和 postgres 数据库中的信息。我什至可以利用新的点字段,这意味着(对我而言)“gis”东西正在工作和配置。
问题
当我尝试运行测试时会出现问题。我收到以下错误:
AttributeError: 'DatabaseOperations' object has no attribute 'geo_db_type'
我相信这发生在 mysql 数据库上,因为我首先得到提示,说明 test_db postgress 数据库存在并且需要删除并重新创建。我输入“是”,它就完成了,然后给了我关于 test_mysql 数据库的相同提示。当我回答“是”时,我得到了错误。
我的旧版应用模型不使用任何新字段;导入是 django.db。所以我想不通为什么测试认为我需要对mysql数据库进行地理空间操作。
我的尝试
1) 注释掉 MySQL 数据库
这确实有效;测试运行良好。但是,这不是一个好的解决方案,原因很明显......
2) 更改 MySQL 的数据库引擎以使用 'django.contrib.gis.db.backends.mysql'
执行此操作时出现不同的错误:
django.db.utils.OperationalError: (1071, 'Specified key was too long; max key length is 767 bytes')
我猜这是由于我的旧模型中某处的复合键。我认为这真的不应该是一个问题,因为我实际上是在后台运行 MariaDB 10.0.31。此外, django.db.backends.mysql 并没有抱怨它。所以我想知道 django.contrib.gis.db.backends.mysql 是否有点过时(因为 MySQL 似乎无论如何都提供有限的空间支持)。
我不明白为什么测试数据库会抱怨,但应用程序似乎工作正常。
提前感谢您提供的任何帮助!我完全被难住了。
支持信息
我的数据库配置如下:
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': os.environ.get('PG_DB_NAME'),
'USER': os.environ.get('PG_DB_USER'),
'PASSWORD': os.environ.get('PG_DB_PASS'),
'HOST': os.environ.get('PG_DB_HOST'),
'PORT': '',
},
'legacy': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.environ.get('MY_DB_NAME'),
'USER': os.environ.get('MY_DB_USER'),
'PASSWORD': os.environ.get('MY_DB_PASS'),
'HOST': os.environ.get('MY_DB_HOST'),
'PORT': '',
},
}
我有一个数据库路由器:
class LegacyRouter(object):
def db_for_read(self, model, **hints):
if model._meta.app_label == 'legacy':
return 'legacy'
return 'default'
编辑:Hacky 解决方法
所以,经过反复试验,我发现我可以通过使用单个 postgresql 数据库进行测试来解决这个问题。我通过添加第二个设置文件并在测试时引用它来完成此操作。
from .settings import *
DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': os.environ.get('TEST_DB_NAME'),
'USER': os.environ.get('TEST_DB_USER'),
'PASSWORD': os.environ.get('TEST_DB_PASS'),
'HOST': os.environ.get('TEST_DB_HOST'),
},
}
DATABASE_ROUTERS = []
在测试时调用如下:
python manage.py test --settings=<module>.test-settings
这对我有用,因为我的遗留数据没有特定于数据库的内容,所以我没有理由不能使用 postgres 进行测试。希望这对其他人有帮助。
编辑:修复
问题出在数据库路由器上。除“旧版”应用外的所有应用都被路由到“默认”数据库(预期),而所有应用加上“旧版”应用都被路由到“旧版”数据库。
为了解决这个问题,我需要一个 allow_migrate 函数。这是我的制作方法:
def allow_migrate(self, db, app_label, model_name=None, **hints):
# Legacy app should only be in legacy database
# Return true if app is legacy and database is legacy
if app_label == 'legacy':
return db == 'legacy'
# Legacy database should only contain legacy app
# Return true if app is not legacy and database not legacy
elif app_label != 'legacy':
return db != 'legacy'
else:
return None
【问题讨论】:
-
请将您的修复添加为单独的答案,而不是将其包含在问题的末尾。这样就很明显你的问题已经解决了。
-
@Alasdair 我已经创建并接受了一个答案,该答案解释了我遇到问题的原因以及我需要做些什么来解决它。为了简洁和减少冗余,答案是指问题中的必要配置。
-
对不起,我没有发现你已经回答了。我的意思是,您的“修复”部分属于答案部分,而不是问题。
标签: mysql django postgis geodjango