how to add dynamic fields at run time in django - python

I have to add dynamic fields at run time in my django application,but I don't know the proper way how to add new fields at run time.
I want to add the code which will generate the dynamic field and will update database too. I am using postgresql database. please help if anyone can.
My "model.py" is simply like this:
class Student(models.Model):
name=models.CharField(max_length=100)
school=models.CharField(max_length=100)
created_at=models.DateField(auto_now_add=True)
is_active=models.BooleanField(default=False)
def __str__(self):
return self.name

Django is not made for dynamic models, as relational databases are not. A model change at runtime will create a ton of problems.
You have to simulate it, by...
clever use of related models
storing values in a large field, e.g. JSON as text
having a generic model that stores the data as key, value; e.g. a table with PK, a FK, key, value as columns.
You should try the first option and only if that does not work out try the other two.

Related

Django - best way to manage existing, auto increment fields with existing data?

This is still in dev, so I am relatively flexible in how to approach this.
So I'm importing data (via fixtures, the import works fine) from an existing database into a django application. The source data is not uniformed in how it manages ID & primary keys. Some tables use what seems to be an auto-increment (similar to what django would produce by default). Others use some sort of integers. The relationships in the data dump are established based on those fields. Seems I can keep on using auto-increments in all cases.
They are conveniently not named uniformly: id, pk, pk_sometablename, etc.
The fixtures I use to import look like this (I generated them using a script based on the datadump, so this can be changed if needs be):
{
"model": "admin_account.client",
"pk": "168",
"fields":
{
"pk_client": "168",
My django model:
class Client(models.Model):
pk_client = models.IntegerField(verbose_name='Pk_client', blank=True, null=True)
I need to be able to import the data in such a way that this field, the pk_client field is used as the primary key (it can still remain as an auto-increment). So I tried to change to this:
class Client(models.Model):
pk_client = models.AutoField(primary_key=True, verbose_name="pk_client", default=-9999)
However if I try this migration with my currently populated dev DB, I get an error:
django.db.utils.OperationalError: foreign key mismatch - "purchase_orders_apent" referencing "admin_client"
I assume django complains because the apent table used to try to lookup client.id, and since I know tell django to use pk_client as the primary key, perhaps those tables referencing it are now unable to find their match). But there's a lot of tables involved.
What the easiest way to manage this?
Should I completely define those models with an empty DB (e.g. define the AutoFields for each model, assign the old db auto-increment value to that same field, and only THEN import the data)?
Or is there something I should change in my fixture definition/the way I import the data?

Implement items ordering in Django

Suppose, I want to build a simple TODO-app. I want to make it possible to create todo-items, and also it should be possible to rearrange items manually.
I made following model:
class Item(models.Model):
title = models.CharField(max_length=500)
Now, I need to add a special field, let's call it order, to keep custom ordering. It should be unique, and it should be greater for any new record, so I tried to make an AutoField.
class Item(models.Model):
title = models.CharField(max_length=500)
order = models.AutoField(primary_key=False)
But it turned out that Django doesn't support several auto fields for a single model.
I guess, it should be possible to write custom raw SQL code and use Postgres sequences directly, but it would look really ugly, and I don't want to write DB-specific code for such simple functionality.
So, here is a question: what is a common way to implement items ordering in Django? It sounds like a very common requirement, and, I think, it should be a simple way to do this.
As it turns out there is no straightforward way to implement this in Django. There are packages which help you, like this one
But I would recommend just look at their model implementation and fit your needs. models.py
You could use Item.objects.count() to automatically increment your field. Plug it in the save() method of your model so that your field is calculated each time you create an instance.

Is it possible to use a table in the database when it is NOT a Django model?

Is it possible get a queryset from a table in the app database that is NOT a model in the app?
If I have a table that is not a model named "cartable", conceptually, I want to do this:
myqueryset = cartable.objects.all()
Is there a relatively easy way to do this? Thanks!
If you want to access an existing table in your database that is not managed by your application, you can still create a class for it, and tell django to ignore it for migrations.
Just create a model and add the fields you need to access and then add a meta class to tell django to leave it alone.
class MyModel(model.Model):
class Meta:
managed = False
you can read about that at https://docs.djangoproject.com/en/1.9/ref/models/options/#managed
To do so you would need to create a class (not a model), with methods that use raw SQL. You should see more details here on how to do so: https://docs.djangoproject.com/en/1.9/topics/db/sql/#executing-custom-sql-directly
Please note that you will have to manually create the object with the right properties afterwards.
If you wanted to use Django ORM without the models, I don't think it is possible. You could however create a model that matches your db in a separate app and never create migrations for it to ensure you don't accidentally modify the DB.
Short answer is, "not really". Django QuerySet deals with model instances, so everything in QuerySet API is tied into models. Everything expects to return model instances, uses model fields etc.
That said, you should be able to create a model for an existing table. You will need to add db_table to the Meta, so Django knows where the table lives. If you have some indexing, you will need to make sure Django's idea of indexes is the same as the one in the database. indexed=True on fields and unique_together in Meta should help a lot with that.

Should I normalize my model or go big-table for this kind of API (of virtual tables)?

I am trying to make a web app that allows users to create "virtual tables" each with its own rows, columns and data. Each user will be able to CRUD their own virtual tables (using an API I am trying to build with django-rest-framework), but they should not be able to see other users' tables.
So far, my first attempt at a model looks like this:
class Vtable(models.Model):
user = models.ForeignKey(User)
table_name = models.CharField(max_length=200)
class Vcolumn(models.Model):
table = models.ForeignKey(Vtable)
column_name = models.CharField(max_length=200)
class Vrow(models.Model):
table = models.ForeignKey(Vtable)
added_date = models.DateTimeField('date added')
class Vdata(models.Model):
table = models.ForeignKey(Vtable)
row = models.ForeignKey(Vrow)
column = models.ForeignKey(Vcolumn)
data = models.CharField(max_length=200)
I just went through the tutorial for the django-rest-framework, and now I am not sure if it makes sense to normalize everything. Would it be better to have one big table instead? I imagine that it would be very very annoying to implement serialization as well as when permissions come into the mix. I am VERY new to Django, I am looking for some guidance.
Thanks in advance!
For this sort of thing you might want to consider storing each set of table data in a JSON field rather than trying to coerce database tables into a style they're not well suited too.
Using a plain JSON field for the table storage may or may not be suitable depending on what kind of lookups (if any) you'll need to perform inside tables, and how much data they'll contain, but it'd certainly be easier to work with.
You could still enforce constraints on the data in the table cells using REST framework's serializers or something similar to that, if you need to ensure that certain cells are of a particular data type.

Django: Overriding verbose_name for AutoField without dropping the model

I am using 0.97-pre-SVN-unknown release of Django.
I have a model for which I have not given any primary_key. Django, consequently, automatically provides an AutoField that is called "id". Everything's fine with that. But now, I have to change the "verbose_name" of that AutoField to something other than "id". I cannot override the "id" field the usual way, because that would require dropping/resetting the entire model and its data (which is strictly not an option). I cannot find another way around it. Does what I want even possible to achieve? If you may suggest any alternatives that would get me away with what I want without having to drop the model/table, I'd be happy.
Hmm... and what about explicitly write id field in the model definition? Like this for example:
class Entry(models.Model):
id = models.AutoField(verbose_name="custom name")
# and other fields...
It doesn't require any underlying database changes.
Look into the command-line options for manage.py; there's a command to dump all of the model data to JSON, and another command to load it back in from JSON. You can export all of your model data, add your new field to the model, then import your data back in. Just make sure that you set the db_column option to 'id' so you don't break your existing data.
Edit: Specifically, you want the commands dumpdata and loaddata.

Categories

Resources