单个 Django 模型,多个表?

2021-11-20 00:00:00 python django mysql

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

解决方案

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

def getModel(db_table):类 MyClass(models.Model):# 像往常一样定义...元类:db_table = db_table返回我的课堂newClass = getModel('29345794_table')newClass.objects.filter( ...

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

def getModel(db_table):类 MyClassMetaclass(models.base.ModelBase):def __new__(cls, name, bases, attrs):名称 += db_table返回models.base.ModelBase.__new__(cls, name, bases, attrs)类 MyClass(models.Model):__metaclass__ = MyClassMetaclass元类:db_table = db_table返回我的课堂

不确定是否可以在已定义的类上动态设置.我自己没有这样做过,但它可能会奏效.

您可以随时设置.

<预><代码>>>>MyModel._meta.db_table = '10293847_table'>>>MyModel.objects.all()

I have several temporary tables in a MySQL database that share the same schema and have dynamic names. How would I use Django to interface with those tables? Can a single model draw data from multiple tables?

解决方案

You could, I believe, make a factory function that would return your model with a dynamic 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( ...

EDIT: Django does not create a new instance of the class's _meta attribute each time this function is called. Creating a new instance for _meta it is dependent upon the name of the class (Django must cache it somewhere). A metaclass can be used to change the name of the class at runtime:

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

not sure if it can be set dynamically on an already-defined class. I haven't done this myself but it might work.

You can set this whenever.

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

相关文章