开发者

What approach is best for mapping a legacy application tables named after years in Django?

开发者 https://www.devze.com 2023-04-05 18:19 出处:网络
Better see what the table names look like: 2009_articles 2010_articles 2011_articles 2009_customers 2010_customers

Better see what the table names look like:

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

Developers have simulated some kind of p开发者_如何转开发artitioning (long before mysql supported it) but now it breaks any try to make a quick frontend so customers can see their invoices and switch years.

After a couple on months I have the following results:

  • Changing Invoice._meta.db_table is useless cause any other relation deduced by the ORM will be wrong

  • models.py cannot get request variables

Option a: Use abstract models so Invoice10 adds meta.db_table=2010 and inherits from Invoice model, and Invoice11 adds meta.db_table=2011, Not DRY although the app shouldn't need to support more than two or three years at the same time, but I will have to still check if

Option b: Duplicate models and change imports on my views: if year == 2010: from models import Article10 as Article

and so on

Option c: Dynamic models as referred to in several places on the net, but why have a 100% dynamic model when I just need a 1% part of the model dynamic?

Option d: Wow, just going crazy after frustration. What about multiple database settings and use a router?

Any help will be much appreciated.


Option e: create new relevant models/database structure, and do an import of the old data in the new structure.


Ugly, but must inform.

I achieved something useful by using Django signal: class_prepared and ThreadLocal to get session:

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)

So is one model class mapping several identical database tables (invoices_01_2013, invoices_02_2013, ...) depending of what month and year the application user is browsing.

Working fine in production.

0

精彩评论

暂无评论...
验证码 换一张
取 消