【问题标题】:Getting data from multiple databases with same tablenames in django在 django 中从具有相同表名的多个数据库中获取数据
【发布时间】:2018-05-24 19:54:07
【问题描述】:

我需要从 Django 中不同的导入 MySQL 数据库中获取数据 (Django 1.11.7,Python 3.5.2)。 我运行manage.py inspectdb --database '<db>',然后在 django 中使用模型。

到目前为止,我只需要访问具有不同名称的表。为此,我在查询集中使用了using 关键字来指定适当的数据库,然后将结果连接起来,如下所示:

from ..models.db1 import Members
from ..models.db2 import Actor

context['db1_data'] = Members.objects.using('db1').filter...
context['db2_data'] = Actor.objects.using('db1').filter...

context["member_list"] = list(chain(
    context["db1_data"],
    context["db2_data"],
))

return context

现在我遇到的问题是两个数据库中存在具有相同模型名称的表。使用上述方法时出现以下错误(我替换了名称):

RuntimeError: Conflicting '<table-name>' models in application '<app>': <class '<app>.<subfolder>.models.<db1>.<table-name>'> and <class '<app>.<subfolder>.models.<db2>.<table-name>'>.

我已经尝试使用不同的名称导入模型,如下所示:

from ..models.db3 import Members as OtherMembers

但错误仍然出现。

from ..models.db1from ..models.db2 是否应该足够清晰,让 Django 发现这两个模型之间的区别?

一种选择可能是重命名模型本身,但这意味着用相同的名称重命名每个数据库模型。由于我将来会使用更多的数据库,所以这不是我的选择。

我尝试了from models import db1, db2 然后db1.Members 等,仍然引发错误。

我读到了元 db_table = 'dbname.tablename'-option,但由于模型是通过 inspectdb 自动生成的,所以它已经在每个类上都有这样的东西:

class MyModel(models.Model):
    <models>

    class Meta:
        managed = False
        db_table = 'my_model'

如前所述,另一个数据库具有完全相同的模型,因此具有相同的元类。我不能也不想更改每个 Meta 类。


编辑:

我的项目结构如下:

app
    -> admin.py
    -> ...
    -> models.py
    -> views.py
    subfolder
        -> models
            -> db1.py
            -> db2.py
        -> views
            -> db1.py
            -> db2.py

【问题讨论】:

  • 我认为问题是,你定义了两个同名的模型类。您可以对任何数据库使用相同的模型(如果两者相同)。它非常适合我。
  • >>> chain(Build.objects.using('ob').all(), Build.objects.using('sb').all())
  • 你是如何导入模型的?如果我从 shell 运行 from .models.db1 import Membersfrom .models.db2 import Members,我会收到上面描述的错误。
  • 是否所有表都将不受管理?是否将两个数据库中的表导入到单个应用程序中?您是否在 settings.py 中设置了两个数据库连接?
  • 是的,目前我们正在使用 sql 文件管理表。所有模型都放在一个文件中。

标签: python mysql django database


【解决方案1】:

假设你已经设置了你的multiple databases correctly:

  1. 您是否尝试添加Custom Router
    如果不遵循文档链接中给出的示例。

  2. 您是否尝试为您的模型使用Custom Manager

    为每个模型创建一个管理器,如下所示:

    class YourModelManagerX(models.Manager):
        def get_queryset(self, *args, **kwargs):
            return super().get_queryset(*args, **kwargs).using('your_db_X')
    

    然后将其作为objects 字段添加到您的适当模型中:

    class YourModel(models.Model):
        ...
        fields
        ...
        objects = YourManagerX()
    
        class Meta:
            managed = False
    

您可能需要同时尝试两者。

【讨论】:

  • @sqe 很高兴知道!节日快乐:)
【解决方案2】:

如果 db1.Members 和 db3.Members 具有相同的定义,则不必为每个数据库单独重新声明 Members 类。

模型.py

...
class Members(models.Model): # Only declared once ever!
    ....

那么,

from Models import Members

context['db1_data'] = Members.objects.using('db1').filter...
context['db3_data'] = Members.objects.using('db3').filter...

... # continue processing

来自 ..models.db1 和来自 ..models.db2 是否应该足够清楚,让 django 发现这两个模型之间的区别?

Django 模型不是特定于数据库的,更像是特定于模式的,因此如果您在两个不同的数据库中拥有同一张表,那么一个扩展 model.Models 的类就足够了。然后,当您尝试检索对象时,可以使用 using() 指定数据库,或者使用路由器,您可以在 Django 文档 https://docs.djangoproject.com/en/2.0/topics/db/multi-db/#an-example 中阅读相关内容

【讨论】:

  • 好吧,正如我所说,这就是我已经做过的。我编辑了我的问题以显示我的应用程序结构。 class Members 也存在于 models.db1models.db2 中。由于我的文件结构,我不能只使用from ..models import Members(生成ImportError: cannot import name 'Members')。我已经在使用context['db1_data'] = Members.objects.using('db1').filter... 语法。还是一样的错误。
  • 您也不必在models.pysubfolder/models/db1.pysubfolder/models/db1.py 中重新定义Members 类。他们的定义没有区别吧?只需在顶级 models.py 文件中定义它们一次,然后无论您想从哪个数据库导入它们,无论您想从哪个数据库导入它们,from models import Members 都可以从该顶级 models.py 导入跨度>
  • 我尝试在我的models.py 文件中定义它们并导入您描述的方式,但不幸的是它抛出了同样的错误。但是,从长远来看,这不是解决方案,因为Members 模型只是我想访问的许多相同模型中的一种。是不是可以在子文件夹中有多个具有相同类的模型文件并使用&lt;folder&gt;.&lt;file&gt;.&lt;model&gt; 之类的语法访问它们?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-31
  • 1970-01-01
  • 2022-06-10
  • 2016-09-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多