【问题标题】:Django 'geo_db_type' AttributeError with Multiple Databases带有多个数据库的 Django 'geo_db_type' AttributeError
【发布时间】: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


【解决方案1】:

回答

问题出在数据库路由器上。除“旧版”应用外的所有应用都被路由到“默认”数据库(预期),而所有应用加上“旧版”应用都被路由到“旧版”数据库。

为了解决这个问题,我需要一个 allow_migrate 函数来阻止除“旧版”应用程序之外的所有应用程序在“旧版”数据库中迁移。有关更多信息,请参阅我的问题中的编辑。

【讨论】:

    猜你喜欢
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    • 2013-08-15
    • 2020-03-22
    • 1970-01-01
    • 2021-08-30
    • 1970-01-01
    相关资源
    最近更新 更多