gpt4 book ai didi

python - Django代理模型到不同的数据库

转载 作者:太空狗 更新时间:2023-10-29 17:31:29 25 4
gpt4 key购买 nike

情况

我们有几个不同的应用程序,它们使用来自工单支持系统的工单来实现不同类型的功能。

首先,我们有一个应用程序,其中有几个模型代表我们的票务支持系统 Kayako 的模型。此应用程序不应了解使用它的其他应用程序的任何信息,并应尽可能保持通用。由于此应用程序使用 Kayako 的现有表,因此我们将其运行在同一数据库上。让我们称这个应用程序 kayakodb .

一个应用程序将客户从我们的客户数据库链接到票证支持系统中的票证。以前,该系统在我们的票证支持系统中拥有自己的票证表示,使用 kayakodb 提供的 API 查询票证。 .然后它使用这种票证表示将客户和域链接到。然而,这太复杂了,而且不太合乎逻辑。因此,我们选择将其切换为代理模型,并将代表客户和域链接的模型移至 kayakodb .让我们称这个应用程序 sidebar .

另一个新应用程序在清晰的概览中显示来自票务支持系统的票证以及电话,因此我们的支持部门可以轻松查看哪些电话和票证与哪些客户相关。本系统有代理模型到sidebar的代理模型,因为一些功能由 sidebar 提供此应用程序还需要模型以及新代理模型声明的其他一些模型。让我们称这个项目WOW .
sidebarWOW应用程序都是同一个项目/存储库的一部分。我们将调用此存储库 Coneybeach它有自己的数据库。然而,kayakodb是一个完全不相关的项目。它包含在 Coneybeach 中通过我们通过 pip 安装的需求文件.

问题

为新设置创建迁移时,Django 为已安装的 kayakodb 创建代理模型迁移。当然,这是不行的。任何时候我们都会安装新版本的 kayakodb它会覆盖此迁移。更不用说kayakodb不应该知道哪些模型使用它。

代码
Ticket模型里面kayakodb :

class Ticket(models.Model):
"""
This model is a representation of the data stored in the "kayako" database table "swtickets". Minus a lot of stuff
we don't use. If you add a field make sure it has the same name as the field in kayako.swtickets.
"""
# Fields, functions and manager etc.

class Meta:
db_table = 'swtickets'
managed = False
SidebarTicket里面的代理模型 sidebar :
from kayakodb.models import Ticket    

class SidebarTicket(Ticket):
class Meta:
# Since this class is a wrapper we don't want to create a table for it. We only want to access the original
# model as we always do, but provide a different interface (when it comes to functions). Proxy models allow us
# to do this: https://docs.djangoproject.com/en/1.10/topics/db/models/#proxy-models
proxy = True

# Don't look for this model in the sidebar tables, but in the kayakodb tables.
app_label = 'kayakodb'

# Some extra functions
Contact类(class) TicketWrapper继承自(根据 Hynekcer 的要求)。此模型用作 TicketWrapper 的基础模型和另一个代表调用的模型(尽管据我所知,这个模型没有问题):
class Contact(models.Model):
type = None

class Meta:
abstract = True

def __getattr__(self, attr):
if attr in ['customers', 'add_customer_id', 'remove_all_customers', 'byters', 'domainnames', 'add_domain_name',
'remove_domain_name', 'add_text', 'remove_text', 'texts', 'creation_date', 'add_tag', 'get_tags',
'remove_tag', 'identifier']:
raise NotImplementedError('You should implement {}'.format(attr))
raise AttributeError(attr)
TicketWrapper里面的代理模型 WOW :
from sidebar.models import SidebarTicket

class TicketWrapper(Contact, SidebarTicket):
class Meta:
# Since this class is a wrapper we don't want to create a table for it. We only want to access the original
# model as we always do, but provide a different interface (when it comes to functions). Proxy models allow us
# to do this: https://docs.djangoproject.com/en/1.10/topics/db/models/#proxy-models
proxy = True

# Don't look for this model in the WOW database, but in the kayakodb database.
app_label = 'kayakodb'

# Some extra functions

我试过什么

  • 我试过不指定 app_label对于两种代理模型。这会创建正确的迁移,但会导致代理模型查找 kayakodb.Ticket Coneybeach 数据库中的模型。
  • 我试过指定 abstract = True对于子类,但不确定这是因为我仍然希望能够将管理器用于模型。
  • 我考虑将当前创建的迁移移至实际 kayakodb项目,但我认为这不是一个好的解决方案。 kayakodb不应该了解其模型的实现或使用它们的位置。
  • ./manage.py check返回 0 个问题。

  • 问题

    如何为位于不同数据库或项目中的模型创建代理模型?

    编辑

    设置后 kayakodb.Ticket非托管模型 WOW项目尝试为 kayakodb 中的所有模型创建迁移.结果:
    Migrations for 'sidebar':
    0004_auto_20170116_1210.py:
    - Delete model Ticket

    Migrations for 'kayakodb':
    0001_initial.py:
    - Create model Staff
    - Create model Tag
    - Create model Ticket
    - Create model TicketPost
    - Create model TicketTag
    - Create model TicketCustomer
    - Create model TicketDomain
    - Create proxy model SidebarTicket
    - Alter unique_together for ticketdomain (1 constraint(s))
    - Alter unique_together for ticketcustomer (1 constraint(s))
    - Create proxy model TicketWrapper

    最佳答案

    正如@hynekcer 所说,如果 kayakodb是现有数据库,需要设置managed = False对于它的所有型号。
    但是,这仍然存在迁移在错误应用程序( kayakodb )中创建的代理模型的问题。

    可能有效的黑客修复正在更改 app_label代理模型到任何可以迁移到的应用程序(在本例中为 sidebar),并制作一个路由器,指向该代理模型从 kayakodb 读取和写入.

    例如代理模型:

    # in sidebar/models.py

    class SidebarTicket(KayakoTicket):
    class Meta:
    proxy = True
    app_label = 'sidebar'

    以及使用它的项目中的路由器:
    from django.conf import settings
    from kayakodb.models import Ticket

    class ProxyDatabaseRouter(object):
    def allow_proxy_to_different_db(self, obj_):
    # check if this is a sidebar proxy to the Ticket model in kayakodb
    return isinstance(obj_, Ticket) and obj_._meta.proxy and obj_._meta.app_label == 'sidebar'

    def db_for_read(self, model, **hints):
    if issubclass(model, Ticket) and model._meta.proxy and model._meta.app_label == 'sidebar':
    return 'kayakodb'
    # the rest of the method goes here

    def db_for_write(self, model, **hints):
    if issubclass(model, Ticket) and model._meta.proxy and model._meta.app_label == 'sidebar':
    return 'kayakodb'
    return None
    # the rest of the method goes here

    def allow_relation(self, obj1, obj2, **hints):
    if self.allow_proxy_to_different_db(obj1) or self.allow_proxy_to_different_db(obj2):
    return True
    # the rest of the method goes here

    关于python - Django代理模型到不同的数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41589508/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com