Django'geo_db_type'包含多个数据库的AttributeError

时间:2017-11-01 18:52:10

标签: mysql django postgis geodjango

背景

我正在使用Django和多个数据库:我有一个Postgres数据库和一个mysql数据库(填充了我正在慢慢转换为Postgres的遗留数据)。

我最近引入了GeoDjango(以django.contrib.gis的形式),其中postgis扩展名用于存储lat / lng信息作为一个点。应用程序本身似乎运行良好。我可以从mysql数据库和postgres数据库中访问信息就好了。我甚至可以利用新的点数字段,这意味着(对我来说)'gis'的东西正在工作和配置。

问题

当我尝试运行测试时会出现问题。我收到以下错误:

AttributeError: 'DatabaseOperations' object has no attribute 'geo_db_type'

我相信这是在mysql数据库上发生的,因为我首先得到提示,指出test_db postgress数据库存在,需要删除并重新创建。我输入'yes',它确实是这样,然后给我关于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

1 个答案:

答案 0 :(得分:0)

答案

问题出在数据库路由器上。除了&#39;遗产&#39;之外的所有应用应用程序被路由到默认&#39;数据库(预期),而所有应用程序加上&#39;遗产&#39;应用程序被转移到“遗产”#39;数据库中。

要解决这个问题,我需要一个allow_migrate函数来阻止除“遗产”以外的所有内容。应用程序来自“遗产”中的迁移&#39;数据库。有关详细信息,请参阅我的问题中的编辑。