[Django]-Dynamic models django

2๐Ÿ‘

You can define your model fields as dict:

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'),
)

Then you can dynamicly create and run migration 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)

Then you can use dynamic model creation to access data in tables:

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 will get general idea.
I took code from project that uses Django 2 (similar code is used to create tables per uploaded CSV file, columns and name of each uploaded CSV is stored in table which is similar to your PrimaryTable).

๐Ÿ‘คViktor Danyliuk

1๐Ÿ‘

You can simplify things by keeping all of the data with the same structure in one table. You can use admin filters and custom manager methods to focus on one type of information at a time, which will provide the same functionality as separate tables.

class Information(models.Model):
    name = models.CharField(db_column='Name', unique=True, max_length=100)
    date = models.CharField(db_column='Date', max_length=100)
    information_type = models.ForeignKey(InformationType, related_name='information_records')

    def __str__(self):
        return self.name


class InformationType(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')

    def __str__(self):
        return self.title
๐Ÿ‘คevergreen

0๐Ÿ‘

k i figure out but i dont know how to write it.

I m going to create 1 class in models:

Example models.py:

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

    class Meta:
        managed = False
        db_table = 'Table_name' # make it args

    def __str__(self):
        return self.url

and in the class Meta i want to implement Args at db_table.

That means when i click on a table in the html i want that table name to be inserted in the db_table and give me the data in it.

Because the class PrimaryTable will give me all the table names in that DB.

I hope i ve explained k. But i still need the answer of how to implement args in the Meta class. and Use it in the views.py and html template.

tables/views.py

def table_base(request):
    table_name = Crawledtables._meta.db_table
    list_tables = Crawledtables.objects.order_by('id')
    table_list = {'list_tables': list_tables}
    return render(request, 'tables/table_base.html', {'table_name': table_name,
                                                      'list_tables': list_tables})


class AboutDetail(DetailView):
    model = Crawledtables
    pk_url_kwarg = 'table_id'
    template_name = 'tables/table_list.html'

    def get_object(self):
        if 'table_id' not in self.kwargs:
            return Crawledtables.objects.get(id=1)
        else:
            return Crawledtables.objects.get(id=self.kwargs['table_id'])

part of tables/views.py

class Details(ListView):
    model = table_name_1
    template_name = 'tables/table_list.html'
    context_object_name = 'details'
    paginate_by = 15
    queryset = table_name_1.objects.all()
๐Ÿ‘คOmega

Leave a comment