dynamic table name and dynamic field for django 1.8 - python

My requirement is: create category and product table according to the store selected.
class Category(models.Model):
parent = models.ForeignKey("Category", blank=True, null=True,
related_name="children", verbose_name=_("Parent Category"))
name = models.CharField(verbose_name=_("Name"), max_length=255)
path = models.CharField(verbose_name=_("Path"), max_length=200)
description = models.TextField(verbose_name=_("Description"))
class CategoryStore(model.Model):
default = models.ForeignKey("Category", related_name="store_category",
verbose_name=_("Default Value"))
parent = models.ForeignKey("CategoryStore", blank=True, null=True,
related_name="children", verbose_name=_("Parent Category"))
name = models.CharField(verbose_name=_("Name"), max_length=255)
description = models.TextField(verbose_name=_("Description"))
store = models.ForeignKey("Store", related_name="store_category",
verbose_name=_("Store"))
CategoryStore model will have table names as category_store_1, category_store_2, etc. Would like to create the tables on the fly after a store is created. If, we add another field to the model, should have option to add to all the tables the new field.
class Product(models.Model):
name = models.CharField(verbose_name=_("Name"), max_length=255)
description = models.TextField(verbose_name=_("Description"))
class ProductStore(model.Model):
default = models.ForeignKey("Product", related_name="store_product",
verbose_name=_("Default Value"))
name = models.CharField(verbose_name=_("Name"), max_length=255)
description = models.TextField(verbose_name=_("Description"))
store = models.ForeignKey("Store", related_name="store_product",
verbose_name=_("Store"))
This also has same requirement as the category. One addition is that, option to create new field to both the model, new field on the fly from admin form. It will be attributes for the product. Instead of another table to store attribute values, want to add a new field to the Product and ProductStore model on the fly.

Not sure if I fully understand your problem, but it seems to me that you should reconsider your database structure. I'm not very experienced but adding tables to db on a regular basis on the fly is not good.
CategoryStore model will have table names as category_store_1, category_store_2, etc.
Keeping in mind that in django 1 model <=> 1 db table, try this approach: one table called CategoryStore which holds data from all your stores and another table called CategoryStoreType with the following structures:
CategoryStore has all the fields you need plus a type field which is a foreign key to CategoryStoreType. CategoryStoreType contains a short description of each store type, e.g. a tuple ('id', 'type name'). This way when you need a new field for one store type you simply add another field to CategoryStore, which holds data of all your store types. (Again, as for tables, adding fields on the fly is not that good, imho.)

Related

Add relationship to three tables with data and strange column names

I have a Postgres database with 3 tables with data and their models in Django. I do not have control over how these tables are filled. But I need to add relationships to them.
It would not be a problem for me in MsSQL, Oracle or MySql. But Im confused here.
class Keywords(models.Model):
id = models.AutoField(primary_key=True)
keyword = models.CharField(unique=True, max_length=250)
class Mapping(models.Model):
id = models.AutoField(primary_key=True)
keyword = models.CharField(max_length=250)
videoid = models.CharField(max_length=50)
class Video(models.Model):
videoid = models.CharField(primary_key=True, max_length=50)
In your model Mapping, which is used to relate with the models Keywords and Video, you can make changes like:
class Mapping(models.Model):
id = models.AutoField(primary_key=True)
keyword = models.ForeignKey(Keywords, on_delete=models.CASCADE)
videoid = models.ForeignKey(Video, on_delete=models.CASCADE)
You also don't need to define id for the model as Django itself creates a id field which is auto generated and primary key.
Use inspectdb in order to generate your models from your db tables.
$ ./manage.py inspectdb table1 table2 table3 >> models.py
Relation
class Video(models.Model):
#...
keywords = models.ManyToManyField(Keywords)
Then you can remove the Mapping model, the table for this relation is generated by Django.
If you want to keep the data of the already related instances, use the through key parameter for the ManyToManyField with the Mapping model.
Finally, I found a solution:
class Mapping(models.Model):
id = models.AutoField(primary_key=True)
video = models.ForeignKey(Videos, to_field='videoid', db_column='videoid', on_delete=models.DO_NOTHING,blank=False,null=True,)
keyword = models.ForeignKey(Keywords, to_field='keyword', db_column='keyword', on_delete=models.DO_NOTHING, blank=False, null=True,)
To add relations to existing tables with weird column names and type it is the best to use to_field and db_column. In this case, Django will not try to create standard id columns for relations.

django foreign key Cannot assign must be a instance

I am developing a web app using Django. I have created the table in MySQL database and then generated the models.py using inspectdb. I am able to fetch details and connect to the database without any issues. But while saving the values to the particular table, below error is shown
sav_list = List(id=4, item_name ='name1', item_desc='desc1', location='location', reason='rfp', pid=3)
Cannot assign "3": "List.id" must be a "Order" instance.
my models
class List(models.Model):
id = models.IntegerField(db_column='ID', primary_key=True) # Field name made lowercase.
item_name = models.CharField(db_column='Item_Name', max_length=255) # Field name made lowercase.
item_desc = models.CharField(db_column='Item_Desc', max_length=300) # Field name made lowercase.
location = models.CharField(db_column='Location', max_length=100, blank=True, null=True) # Field name made lowercase.
reason = models.CharField(db_column='Reason', max_length=100, blank=True, null=True) # Field name made lowercase.
pid = models.ForeignKey('Order', models.DO_NOTHING, db_column='PID') # Field name made lowercase.
class Order(models.Model):
poid = models.IntegerField(db_column='POID', primary_key=True) # Field name made lowercase.
po = models.CharField(db_column='PO', unique=True, max_length=20) # Field name made lowercase.
quote = models.CharField(db_column='Quote', unique=True, max_length=20) # Field name made lowercase.
condition = models.CharField(db_column='Condition', max_length=15) # Field name made lowercase.
I have tried relate_name for foreign key but still same behaviour. Same values can be stored on database without any issues. Only Django throws an error.
Please someone help me!!!
You should paste the actual error; it is presumably that "List.pid" must be an "Order" instance.
The error should be clear. pid is a ForeignKey field, it expects an instance of the related model. You can either get the item and set it:
pid = Order.objects.get(pk=3)
List(...., pid=pid)
or use the underlying id field:
List(...., pid_id=3)
The pid column at the Django level is not an id (integer), yes on the database level it is. But in Django it is a foreign key, and thus it refers to an Order instance. You thus should pass it an Order instance (the one that corresponds to poid=3).
But we are lucky, in case you construct such ForeignKey, Django automatically makes a field_id column that stores the id, and those two fields act like twins. We can thus assign 3 to pid_id:
sav_list = List(
id=4,
item_name ='name1',
item_desc='desc1',
location='location', reason='rfp',
pid_id=3
)
Note however that for most database backend, foreign key constraints will check if there is an Order instance with as referenced column (in Django the primary key) 3 exists. If not, it is impossible to create such List. I would therefore advice to ensure that such Order exists before trying to save it to the database.

Add number field to Django model

I have a django movie model
class Film(models.Model):
title = models.CharField(max_length=200)
movie_id = models.CharField(max_length=8, unique=True, primary_key=True)
director = models.ForeignKey('Director', on_delete=models.SET_NULL, null=True)
year = models.IntegerField(null=True)
genres = models.ManyToManyField(Genre)
I need to use movie_id as primary key, but also i need a field, which represents number of item's row in table.
It must increment automatically, just like standard "id" field.
How can i add it?
This question https://stackoverflow.com/users/3404040/take-care is similar, but i can't use my "number" field as primary key, because movie_id is already used for that.
You can use something like this, but it can be resource consuming if you do not want to use the default id field.
class Film(models.Model):
def number():
no = Film.objects.count()
return no + 1
movie_row = models.IntegerField(unique=True,default=number)
From Django's Documentation:
By default, Django gives each model the following field:
id = models.AutoField(primary_key=True)
This is an auto-incrementing primary key.
If you’d like to specify a custom primary key, just specify primary_key=True on one of your fields. If Django sees you’ve explicitly set Field.primary_key, it won’t add the automatic id column.
Each model requires exactly one field to have primary_key=True (either explicitly declared or automatically added).
If you want yours to explicitly be called movie_id you probably need something like:
class Film(models.Model):
movie_id = models.AutoField(primary_key=True)

Foreign key choosable when create the model instance

I have two models:
class Amodel(models.Model):
name = models.CharField(max_length=8)
desc = models.CharField(max_length=256)
class Bmodel(models.Model):
name = models.CharField(max_length=8)
desc = models.CharField(max_length=256)
now I have another model:
class Cmodel(models.Model):
name = models.CharField(max_length=8)
f_model = models.ForeignKey(to='there I want to dynamic refers to Amodle or Bmodel when create the Cmodel instance')
I want the Cmodel's f_model is choosable when Create the Cmodel instance, whether this is possible?
This feature called generic relations. Here is the official documentation link generic-relations
By definition of foreign key you can not assign foreign key to one field with choices of model
A FOREIGN KEY is a key used to link two tables together.
A FOREIGN KEY is a field (or collection of fields) in one table that refers to the PRIMARY KEY in another table.
Instead you can proceed to create two fields as below:
class Cmodel(models.Model):
name = models.CharField(max_length=8)
f_a_model = models.ForeignKey(Amodel, blank=True, null=True, on_delete=models.CASCADE)
f_b_model = models.ForeignKey(Bmodel, blank=True, null=True, on_delete=models.CASCADE)
This way you can create two fields and you can keep it as null.
So If you wish to proceed for Cmodel instance with foreign key of a model you can add it to field f_a_model and keep f_b_model null and vice versa
You may follow example of using generic-relations from this link and the doc.
When you use generic relations you need to write your own custom field and method for serializer or form or anywhere you wish to user it.

django: where to find models field type translation to postgres

I am trying to compare the table of a given database with an app's model definitions.
class SewManAbstract(models.Model):
"""
"""
display_name = models.CharField(max_length=255, blank=True)
code = models.CharField(
max_length=100, blank=True,
help_text='txt')
length = models.FloatField(_("length"), null=True, help_text='input')
When I query the database directly for metadata, I get
meta = ([u'display_name', u'character varying(255)',
u'code', u'character varying(100)',
u'length', u'double precision'])
When I use django's build-in functionality
FieldNameType = collections.namedtuple(
"FieldNameType", 'field_name, field_type')
tmp = []
for field in model._meta.local_fields:
fn = FieldNameType(
field.name, model._meta.
get_field(field.name).get_internal_type())
tmp.append(fn)
I get
[FieldNameType(field_name='display_name', field_type=u'CharField'),
FieldNameType(field_name='code', field_type=u'CharField'),
FieldNameType(field_name='length', field_type=u'FloatField')]
Comparing the two different outputs won't be easy. So my question really is: where can I find django's internal translation of a model field type to the corresponding postgres field type?
You can find this translation in this module (django.db.backends.postgresql_psycopg2.base) in DatabaseWrapper class's data_types attribute.

Categories

Resources