I have several 开发者_JAVA技巧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()
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)...']
combined many stackflow answer to reach this
#connection should be passed from the django_project #using django.db import connection
class multiModel():
def __init__(self, model_name, table_name, prototype, app_name, connection) -> None:
"""
@model_name: name of the new table object
@table_name: name of the table with which it has to
be created in database
@prototype: model which has to be used as prototype for
creating new table
@app_name: app for which table has to be created
@connection: connection to be used
"""
self.model_name = model_name
self.table_name = table_name
self.prototype = prototype
self.app_name = app_name
self.connection = connection
self.name_table_db = f"{self.app_name}_{self.table_name}"
def get(self):
if self.__exists__():
Model = self.__create_model__(create=False)
else:
Model = self.__create_model__()
return Model
def __exists__(self):
with self.connection.cursor() as cursor:
cursor.execute("show tables;")
tables = [each[0] for each in cursor.fetchall()]
result = False
if self.name_table_db.lower() in tables:
result = True
return result
def __create_model__(self, create = True):
class Meta:
pass
setattr(Meta, "db_table", self.name_table_db)
#self.db_table = f"{self.app_name}_{self.table_name}"
fields = {}
for field in self.prototype._meta.fields:
fields[field.name] = field.clone()
attrs = {'__module__':f"{self.app_name}.models", "Meta":Meta}
self.attrs = attrs
attrs.update(fields)
model = type(self.model_name, (models.Model,), attrs)
if create:
with self.connection.schema_editor() as schema_editor: schema_editor.create_model(model)
return model
精彩评论