Create tables dynamically and operate them through Django ORM.
Dynamically creating a model is actually to generate the Model class at runtime. This can be achieved through a function, passing parameters (today's date, such as: 20181211), and then generating a new model class. The
db_table in Meta is
def get_log_model(prefix): table_name = 'log_%s' % str(prefix) LOG_LEVELS = ( (0, 'DEBUG'), (10, 'INFO'), (20, 'WARNING'), ) class LogMetaclass(models.base.ModelBase): def __new__(cls, name, bases, attrs): name += '_' + prefix # This is the name of the Model. return models.base.ModelBase.__new__(cls, name, bases, attrs) class Log(models.Model): __metaclass__ = LogMetaclass level = models.IntegerField(choices=LOG_LEVELS) msg = models.TextField() time = models.DateTimeField(auto_now=True, auto_now_add=True) @staticmethod def is_exists(): return table_name in connection.introspection.table_names() class Meta: db_table = table_name return Log
As you can see, different Log Classes are generated through functions. Pay attention to
__metaclass__. Metaclasses can change the name of the model at runtime. The name of the table can be defined by
db_table, and the name of the class can be defined by overriding the metaclass.
print cls.__name__ Log_20181211 print cls._meta.db_table log_20181211
Use the direct function to obtain the Log model of the current date, and then use is_exists to determine whether the table is created, and create the corresponding table if it is not created.
def index(request): today = date.today().strftime("%Y%m%d") # RuntimeWarning: Model '__main__.logclasslog_' was already registered. # Reloading models is not advised as it can lead to inconsistencies # most notably with related models. # As mentioned in the above warning, Django does not recommend reloading Model definitions. # As a demo, it can be obtained directly through get_log_model, ignoring the warning. # So here first get the registered Model through all_models, # If it is not available, generate a new model. try: cls = apps.get_model('__main__', 'Log_%s' % today) except LookupError: cls = get_log_model(today) if not cls.is_exists(): with connection.schema_editor() as schema_editor: schema_editor.create_model(cls) log = cls(level=10, msg="Hello") log.save() return HttpResponse('<h1>%s</h1>' % cls._meta.db_table)
Get the cls part above, the code here is first obtained through the registered
all_models of apps, otherwise the second execution of a model definition code will throw a
RuntimeWarning warning, the model will be registered in the initialization function of the model, it is best not to repeat the registration . First get the model through
apps.get_model, if not, then initialize the new model through
get_log_model. This is a bit safer.