单个 Django 模型,多个表?

Posted

技术标签:

【中文标题】单个 Django 模型,多个表?【英文标题】:Single Django model, multiple tables? 【发布时间】:2011-06-29 12:17:09 【问题描述】:

我在 mysql 数据库中有几个临时表,它们共享相同的架构并具有动态名称。我将如何使用 Django 与这些表进行交互?单个模型可以从多个表中提取数据吗?

【问题讨论】:

你可以动态设置它如下更新。 【参考方案1】:

我相信,您可以创建一个工厂函数,以动态 db_table 返回您的模型。

def getModel(db_table):
  class MyClass(models.Model):
     # define as usual ...
     class Meta:
       db_table = db_table

  return MyClass

newClass = getModel('29345794_table')
newClass.objects.filter( ...

编辑:Django 不会在每次调用此函数时创建类的 _meta 属性的新实例。为_meta 创建一个新实例取决于类的名称(Django 必须将其缓存在某处)。元类可用于在运行时更改类的名称:

def getModel(db_table):
  class MyClassMetaclass(models.base.ModelBase):
    def __new__(cls, name, bases, attrs):
      name += db_table
      return models.base.ModelBase.__new__(cls, name, bases, attrs)

  class MyClass(models.Model):
    __metaclass__ = MyClassMetaclass

    class Meta:
      db_table = db_table

  return MyClass

不确定是否可以在已定义的类上动态设置。我自己没有这样做,但它可能会起作用。

您可以随时设置。

>>> MyModel._meta.db_table = '10293847_table'
>>> MyModel.objects.all()

【讨论】:

我认为您的第一个解决方案在我的情况下更好,因为我将有许多必须与之交互的表,并且我不确定动态设置它是线程安全的解决方案.我发现的问题是在测试时会出现奇怪的结果,即必须进行一些争吵才能加载夹具,即使这样也会出现一些奇怪的行为。 对于您的第一个解决方案,db_table 似乎卡在了第一个分配的位置。可以重新赋值,但是对于类的每一个实例都会重新赋值(换句话说,好像_meta的实例只有一个)。 第二种解决方案对我有用。保存记录:myClass = get_model('tableName') t = myClass(description='nice' # 设置列值 t.save() 在多线程中使用MyModel._meta.db_table会不会很危险? 对于 Python 3 代码类 MyClass(models.Model): __metaclass= MyClassMetaclass 应该像这个类 MyClass(models.Model, metaclass= MyClassMetaclass):【参考方案2】:

为您的表格动态创建模型。

from django.db import models
from django.db.models.base import ModelBase

def create_model(db_table):

    class CustomMetaClass(ModelBase):
        def __new__(cls, name, bases, attrs):
            model = super(CustomMetaClass, cls).__new__(cls, name, bases, attrs)
            model._meta.db_table = db_table
            return model

    class CustomModel(models.Model):

        __metaclass__ = CustomMetaClass

        # define your fileds here
        srno = models.IntegerField(db_column='SRNO', primary_key=True)

    return CustomModel

你可以开始查询数据库了。

In [6]: t = create_model('trial1')

In [7]: t._meta.db_table
Out[7]: 'trial1'

In [8]: t.objects.all()  # default db
Out[8]: [<CustomModel: CustomModel object>, '(remaining elements truncated)...']

In [9]: t.objects.using('test').all()  # test db
Out[9]: [<CustomModel: CustomModel object>, '(remaining elements truncated)...']

【讨论】:

这是最好的答案。我已经进入 Django 源代码,发现任何继承自 models.Model 的模型都会被缓存。所以meta class需要设置不同的model name(缓存键),设置不同的model._meta.db_table 惊人的答案!但是这样的解决方案将如何处理数据库迁移、表创建和方案更新?是否可以使用现有表名列表来支持通常的 Django 方案升级?

以上是关于单个 Django 模型,多个表?的主要内容,如果未能解决你的问题,请参考以下文章

我可以将单个 Django 模型字段拆分为多个 Django Rest Framework 序列化器字段吗?

如何在 django 模型中从一个字段添加多个输入

如何在 Django 中删除单个模型,并留下其他模型

我可以对多个表使用单个 CodeIgniter 模型吗?

多个 django 会话表

在 joomla 3.0 中使用单个模型从表单写入多个表