How to use Dynamic fields in models? - django

I want to use a dynamic field in django means I have one model whose one is what be specified in the other model.
I hope i can explain it to you through example.
I have one model name product and each time a new product is uploaded we have to set some attributes for that and that attributes are specified in the 2nd table means in this product model one field is dynamic which depends on the 2nd table. if i select 'x' in other table then that field is shown here and if i select 'y' then that will be shown here,So that based on that product id and attribute id I can specify the attribute value in 3rd table so that in future i can fetch that value for a specified product.
I have tried this a lot but i do not know how to use dynamic fields in django, So can anybody let me know how i can do this.
Thanks

I recommend you to use django-json-field for that purpose ( https://github.com/derek-schaefer/django-json-field ). It uses only one Text field in your db, but you can access objects in your json like a python objects:
json = JSONField() #in your model
json = "{'attributes':{'colour':'blue','size':'2'}, 'image-height':'200px'}" # in your db
{{product.json.attributes}} #in your template
product.json.attributes #in your views
It's a great way to make many 'django' fields, while storing it only in one Text field in db.
The disadvantages of this approach is that you can't effectively search for the fields using your database, but if you have a few dozens of products, you can do the filter by python right in view.

Related

Dynamic Model in Django from fields data in another model

I am working on a project where I have 2 models model
class Customer(models.Model):
name = models.CharField(...)
...
class CustomerProperty(models.Model):
name = models.CharField(...)
type = models.CharField(...)
code = models.CharField(...)
The CustomerProperty table has rows inside based on a parquet file (created at database init, not changed later on). For column in the parquet file, CustomerProperty has a row with column name from parquet as name in the table.
Now for some other purpose, I need to copy over all the data in the parquet file inside the db. So, for each row in the CustomerProperty table, this new table will have a column (plus one column for foreign key to Customer) so I can run filters based on property values. This will also be copied over at db init and not change later on, so it is an unmanaged django model.
I can't find any good docs on this, how to create a django model dynamically or how to add fields to that model dynamically. I don't need it to be managed, no need of migrations or django admin view support. I only need it to work with django ORM and be able to join and filter on it.
I've read the docs and didn't find much. Most of the answers talk about why this is a bad idea but I don't see any other way of solving my problem (I have few other tables joined together to run a complex query and I need to do further filtration based on these properties and support pagination.

Django and Postgres inserting into many-to-many table not working

I'm using python and psycopg2 to scrape some data and insert them into my database.
I've already created the movies and actors tables inside my Django models.py and inside my movies table, there is a many to many relationship between movies and actors table.
below is my models.py:
class Movie(models.Model):
name = models.CharField(max_length=55)
summary = models.TextField(max_length=1024)
actor = models.ManyToManyField(Actor, blank=True)
when I create a movie from Django-admin I select which actors are included in the movie and everything works fine and all the related actors for that movie will show up on my website.
But the problem is that when I try to insert scraped data into my database outside of my Django project folder, the related actors won't be shown on my website because obviously, I have not set the many to many relationship between them.
I have tried creating a junction table using SQL commands which gets the movie id and the actor's id and links them together but I don't know how I should tell Django to use that table and show the related actors for each movie.
This is the SQL code I use to insert into my db:
INSERT INTO movies(name, summary)
VALUES ('movie name', 'sth')
and the code to insert to actors table:
INSERT INTO actors(name, bio)
VALUES ('actorname', 'sth')
Both actors and movies table have auto generated id and I insert them insto the junction table using the code below:
INSERT INTO movie_actors (actor_id, movie_id)
VALUES (
(SELECT actor_id from actors where name='actor name'),
(SELECT movie_id from movie where name='movie name')
)
Am I doing it right?
I would really appreciate it if someone could help me with this.
Django automatically creates a table for many2many relationships. From docs:
ManyToManyField.through
Django will automatically generate a table to manage many-to-many relationships. However, if you want to manually specify the intermediary table, you can use the through option to specify the Django model that represents the intermediate table that you want to use.
The most common use for this option is when you want to associate extra data with a many-to-many relationship.
So you must find the name of the table that django had already created.
Secondly, I suggest that you use django's ORM instead of raw queries so you don't have these kind of problems anymore.
Django automatically creates a through table for M2M relations, if you need you can specify custom through table. In your case I think there is no need of custom through table.
I using Django ORM instead of writing raw query.
INSERT INTO movies(name, summary) VALUES ('movie name', 'sth')
instead of tis raw query you can use the following ORM query:
movie = Movie.objects.create(name="movie name", summary="movie sammuary")
This will create a movie entry in the Movie table.
Next to create user entry you can use the following query:
actor = Actor.objects.create(name="actor name", bio="actor bio")
Now you created the entries in both the table, next you can establish the realtion, for that you have to use the following query:
movie.actor.add(actor)
Incase if you want to add multiple actors at the same time, you create multiple actors object and use following query:
movie.actor.add(actor1, actor2, actor2)
For more details you can check django's offical documentation

How to get list of all fields corresponding to a model saved in content type framework in django

I have this requirement in which I have to show two dropdown fields on Django admin page.
The first field will be the dropdown of all the table names available in my project, and the second field will be a dropdown all the available fields of the table selected in 1st dropdown. The second field will be dynamic based on the selection of the first dropdown. I am planning to handle this by overriding change_form_template.
Now, I can show the dropdown of table names by fetching them through content type Django model, But not able to fetch corresponding fields as content type model save the model name as a string. So is there any way not necessarily using Content-Type to achieve such a requirement?
Any help around that will be highly appreciated.
Thank you.
Here you have dependency of another fields right so i think you need to see i give link,then yo get error let me know
link:hint of dependency field in django

Should I use ArrayField or ManyToManyField for tags

I am trying to add tags to a model for a postgres db in django and I found two solutions:
using foreign keys:
class Post(models.Model):
tags = models.ManyToManyField('tags')
...
class Tag(models.Model):
name = models.CharField(max_length=140)
using array field:
from django.contrib.postgres.fields import ArrayField
class Post(models.Model):
tags = ArrayField(models.CharField(max_length=140))
...
assuming that I don't care about supporting other database-backends in my code, what is a recommended solution ?
If you use an Array field,
The size of each row in your DB is going to be a bit large thus Postgres is going to be using more toast tables
Every time you get the row, unless you specifically use defer the field or otherwise exclude it from the query via only, or values or something, you paying the cost of loading all those values every time you iterate across that row. If that's what you need then so be it.
Filtering based on values in that array, while possible isn't going to be as nice and the Django ORM doesn't make it as obvious as it does for M2M tables.
If you use M2M field,
You can filter more easily on those related values
Those fields are postponed by default, you can use prefetch_related if you need them and then get fancy if you want only a subset of those values loaded.
Total storage in the DB is going to be slightly higher with M2M because of keys, and extra id fields.
The cost of the joins in this case is completely negligible because of keys.
With that being said, the above answer doesn't belong to me. A while ago, I had stumbled upon this dilemma when I was learning Django. I had found the answer here in this question, Django Postgres ArrayField vs One-to-Many relationship.
Hope you get what you were looking for.
If you want the class tags to be monitored ( For eg : how many tags, how many of a particular tag etd ) , the go for the first option as you can add more fields to the model and will add richness to the app.
On the other hand, if you just want it to be a array list just for sake of displaying or minimal processing, go for that option.
But if you wish to save time and add richness to the app, you can use this
https://github.com/alex/django-taggit
It is as simple as this to initialise :
from django.db import models
from taggit.managers import TaggableManager
class Food(models.Model):
# ... fields here
tags = TaggableManager()
and can be used in the following way :
>>> apple = Food.objects.create(name="apple")
>>> apple.tags.add("red", "green", "delicious")
>>> apple.tags.all()
[<Tag: red>, <Tag: green>, <Tag: delicious>]

Fine tuning Django queryset retrieval

In a Django app of mine, I need to display, for a list of users (called user_ids), their:
username, avatar and score.
The username is retrieved from the User model, whereas avatar and score are present in the UserProfile model (that has a one-to-one field point to the User model, called user).
Currently my approach is to fetch the full objects (see below), even though I just need 3 attributes from the two models.
What's the most efficient way for me to just retrieve just the required fields, nothing else? Now I know i can do:
usernames = User.objects.filter(id__in=user_ids).values_list('username',flat=True)
scores_and_avatars = UserProfile.objects.filter(user_id__in=user_ids).values_list('score','avatar')
However, these give me separate querysets, so I can't iterate over them as a unified object_list and show each user's username, score and avatar in a Django template. So what would be the most efficient, light-weight way to retrieve and put this information together?
Currently, I'm doing the following to retrieve these three fields: queryset = User.objects.select_related('userprofile').filter(id__in=user_ids)
The most efficient way it's use values, your query will look like this:
usernames = User.objects.filter(id__in=user_ids).values('username', 'userprofile__score', 'userprofile__avatar')
This solution will return dictionary, but you can try to use only instead of values, it'll create django model object with specified fields, but if you will try to access not specified field it'll generate additional query.
usernames = User.objects.filter(id__in=user_ids).select_related('userprofile').only('username', 'userprofile__score', 'userprofile__avatar')