Python – Dynamic model django

Dynamic model django… here is a solution to the problem.

Dynamic model django

Let’s say I have 10 tables in 1 db, the table names are different, the data is different, but the structure of the tables is the same. Then I also have 1 table to collect all the table names and the creation date of that table.

Example:

PrimaryTable
table_name_1
table_name_2
....
table_name_10

and examples of the structure of all tables:

class PrimaryTable(models. Model):
    name = models. CharField(db_column='Name', unique=True, max_length=100)
    date = models. CharField(db_column='Date', max_length=100)

class Meta:
        managed = True
        db_table = 'Primary Table'

def __str__(self):
        return self.name

class table_name_1(models. Model):
    title = models. TextField(db_column='Title', blank=True, null=True)
    url = models. CharField(db_column='Url', unique=True, max_length=250, blank=True,
                           null=True)
    description = models. TextField(db_column='Description', blank=True, null=True)
    created_at = models. DateTimeField(db_column='Created_at')

class table_name_2(models. Model):
    title = models. TextField(db_column='Title', blank=True, null=True)
    url = models. CharField(db_column='Url', unique=True, max_length=250, blank=True,
                           null=True)
    description = models. TextField(db_column='Description', blank=True, null=True)
    created_at = models. DateTimeField(db_column='Created_at')

And so on….

I

just want to create a class that contains all the tables with the same structure and call it when I select the table from the PrimaryTable.

I

don’t want to use “python manage.py inspectdb > models.py” every time I create a table. I want to access it immediately when I create a new table.

Solution

You can define model fields as dictionaries:

fields = dict(
    title = models. TextField(db_column='Title', blank=True, null=True),
    url = models. CharField(db_column='Url', unique=True, max_length=250, blank=True, null=True),
    description = models. TextField(db_column='Description', blank=True, null=True),
    created_at = models. DateTimeField(db_column='Created_at'),
)

You can then dynamically create and run migrations for it:

from django.db import connection, migrations, models
from django.db.migrations.executor import MigrationExecutor

def create_table(table_name, model_fields, app_label):
    class Migration(migrations. Migration):
        initial = True
        dependencies = []
        operations = [
            migrations. CreateModel(
                name=table_name,
                fields=[
                    ('id', models. AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ] + [(k, field) for k,field in model_fields.items()],
                options={
                    'db_table': table_name,
                },
            ),
        ]
    executor = MigrationExecutor(connection)
    migration = Migration(table_name, app_label)
    with connection.schema_editor(atomic=True) as schema_editor:
        migration.apply(executor._create_project_state(), schema_editor)

You can then use dynamic model creation to access the data in the table:

from django.db import models

def create_model(name, fields=None, app_label=None, module='', options=None, admin_opts=None):
    """
    Create specified model
    """
    class Meta:
        db_table = name
    if app_label:
        # app_label must be set using the Meta inner class
        setattr(Meta, 'app_label', app_label)
    # Update Meta with any options that were provided
    if options is not None:
        for key, value in options.iteritems():
            setattr(Meta, key, value)
    # Set up a dictionary to simulate declarations within a class
    attrs = {'__module__': module, 'Meta': Meta}
    # Add in any fields that were provided
    if fields:
        attrs.update(fields)
    # Create the class, which automatically triggers ModelBase processing
    model = type(name, (models. Model,), attrs)
    return model

I hope you can get an overview of it.
I got the code from a project using Django 2 (similar code is used to create a table for each uploaded CSV file, with the columns and names of each uploaded CSV stored in a table similar to your PrimaryTable).

Related Problems and Solutions