什么方法最适合在 Django 中映射以多年命名的遗留应用程序表?

Posted

技术标签:

【中文标题】什么方法最适合在 Django 中映射以多年命名的遗留应用程序表?【英文标题】:What approach is best for mapping a legacy application tables named after years in Django? 【发布时间】:2011-11-20 10:55:00 【问题描述】:

最好看看表名是什么样子的:

2009_articles 2010_articles 2011_articles 2009_customers 2010_customers 2011_customers 2009_invoices 2010_invoices 2011_invoices

开发人员已经模拟了某种分区(早在 mysql 支持它之前),但现在它打破了任何尝试制作快速前端以便客户可以查看他们的发票和切换年份的尝试。

几个月后,我得到了以下结果:

更改 Invoice._meta.db_table 没有用,因为 ORM 推导出的任何其他关系都会出错

models.py 无法获取请求变量

选项 a: 使用抽象模型,所以 Invoice10 添加 meta.db_table=2010 并继承自 Invoice 模型,Invoice11 添加 meta.db_table=2011,Not DRY 虽然应用程序不需要同时支持超过两三年,但我仍需检查是否

选项 b: 复制模型并根据我的观点更改导入: 如果年份 == 2010: 从模型中导入 Article10 作为文章

等等

选项 c: 网上好几个地方都提到了动态模型,但是我只需要模型动态的 1% 部分,为什么还要有 100% 的动态模型呢?

选项 d: 哇,挫败后简直要疯了。多个数据库设置并使用路由器呢?

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

选项 e:创建新的相关模型/数据库结构,并在新结构中导入旧数据。

【讨论】:

:D 当你也必须保留原始应用程序时怎么办?假设不同的用户配置文件(或设备)使用不同的前端,但数据相同。 (谢谢)【参考方案2】:

丑陋,但必须告知。

我通过使用 Django 信号实现了一些有用的功能:class_prepared 和 ThreadLocal 来获取会话:

from django.db.models.signals import class_prepared
from myapp.middlewares import ThreadLocal

apps = ('oneapp', 'otherapp',)

def add_table_prefix(sender, *args, **kwargs):
    if sender._meta.app_label in apps:
        request = ThreadLocal.get_current_request()
        try:
            year = request.session['current_year']
        except:
            year = settings.CURRENT_YEAR
        prefix = getattr(settings, 'TABLE_PREFIX', '')
        sender._meta.db_table = ('%s_%s_%s_%s') % (prefix, year, sender._meta.coolgest_prefix, sender._meta.db_table)

class_prepared.connect(add_table_prefix)

根据应用程序用户浏览的月份和年份,一个模型类映射多个相同的数据库表(invoices_01_2013、invoices_02_2013...)也是如此。

在生产中运行良好。

【讨论】:

这对 Django 1.7 是否适用?我正在升级 1.5 站点,新的初始迁移使用默认表名。 是的,它工作正常(用 1.8 交叉手指) 新问题是 django 1.7 与旧模型验证您没有使用两次相同的 column_name,但其他一切都很好。

以上是关于什么方法最适合在 Django 中映射以多年命名的遗留应用程序表?的主要内容,如果未能解决你的问题,请参考以下文章

什么时候适合使用 Django 上下文处理器?

Django命名空间app_name和namespace

django 路由系统

学习Linux系统的方法有很多,适合自己的才是最好。

[Django]部署(一)

什么是最适合云数据库的架构设计?