Single Django model, multiple tables?

后端 未结 2 694
失恋的感觉
失恋的感觉 2020-11-29 22:01

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 mo

相关标签:
2条回答
  • 2020-11-29 22:12

    Create a model for your table dynamically.

    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
    

    and you can start querying the database.

    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)...']
    
    0 讨论(0)
  • 2020-11-29 22:29

    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()
    
    0 讨论(0)
提交回复
热议问题