Django: query of a foreign key of a foreign key - python

This might be stupid question and I am sure that there is a basic query for this situation, but I don't seem to get a hang of it and Google turned out to be a miss for solution.
I have models:
Project, primary key=project_no;
Under project there are product_config models, primary key=id;
Under each product_config there is a pre_config model, primary key=product_id;
Under each pre_config there is a list of sub_config models, primary key=id;
Now I am loading a page for project details and I pass a project_no and make a query for all product_configs:
project.objects.get(project_no=project_no)
product_config.objects.filter(project_no=project_no)
Now I want to create a table for the list of sub_configs according to pre_config under product_config. In a shell I can query the list with:
config_assembly.objects.filter(product_id=product_id)
How I can pass the product_id of pre_config from my product_config to query all the sub_configs?
EDIT:
This is the basic structure of my models.
in project.models
class project(models.Model):
project_no = IntegerField('project no', primary_key=True)
class product_config(models.Model):
project_no = models.ForeignKey('project.project', on_delete=models.CASCADE, verbose_name='project no')
product_id = models.ForeignKey('product.pre_config', on_delete=models.CASCADE, verbose_name='product code')
in product.models
class pre_config(models.Model):
product_id = models.CharField('product code', max_length=30, unique=True, primary_key=True)
class sub_config(models.Model):
subproduct_id = models.CharField('subproduct code', max_length=20, unique=True, primary_key=True)
in assembly.models
class config_assembly(models.Model):
product_id = models.ForeignKey('product.pre_config', on_delete=models.CASCADE, verbose_name='product code')
subconfig_id = models.ForeignKey('product.sub_config', on_delete=models.CASCADE, verbose_name='subproduct code')

For your use case it sounds like you want to use the API for related objects.
If I'm understanding your question correctly, here's an example:
# Of course, you should handle cases when 0 or multiple product_configs
# match the query, and replace QUERY with an actual selector.
# This is the related pre_config's product_id
my_pre_config = product_config.objects.get(QUERY).product_id
assemblies = my_pre_config.config_assembly_set.all()
(I follow this standard for class names, so I may be mistaken about _set in your case. It could be configassembly_set.)
You can then iterate over assemblies to get the sub config of each config_assembly, like so: assembly.subconfig_id.
Also, for the purposes of readability, I would recommend renaming your foreign key fields from foo_id to something signifying the actual model that the foreign key points to. For example:
# models.py
class product_config(models.Model):
project = models.ForeignKey('project.project', on_delete=models.CASCADE)
Even though the database values will be IDs, in your code you probably want to reference my_product_config.project.project_no instead of my_product_config.project_no.project_no, which can get confusing and lead to mistaking model instances for raw ID values, and vice-versa.

Related

Adding Foreign Key to model - Django

class Plans(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=255)
plan_type = models.CharField(max_length=255)
class Order(models.Model):
id = models.IntegerField(primary_key=True)
selected_plan_id = models.IntegerField(primary_key=True)
Order's selected_plan_id is Plans's id.
Which model should I add a foreign key to? How?
First of all there are some bad ways to pointout:
two fields cannot be primary keys in a table
also django as default includes primary key id in every table, so no need to add id field.
You should be doing this way:
class Order(models.Model):
selected_plan_id = models.ForeignKey(Plans, on_delete=models.CASCADE)
The solution that you are looking for
class Order(models.Model):
id = models.IntegerField(primary_key=True)
selected_plan_id = models.ForeignKey(Plans, on_delete=models.CASCADE)
The purpose of using models.CASCADE is that when the referenced object is deleted, also delete the objects that have references to it.
Also i dont suggest to you add 'id' keyword to your property, django makes automatically it. If you add the 'id' keyword to end of the your property like this case, you gonna see the column called 'selected_plan_id_id' in your table.
class Order(models.Model):
id = models.IntegerField(primary_key=True)
selected_plan_id = models.IntegerField(primary_key=True)
Plain= models.ForeignKey(Plain)
Check the dependence of the table and after getting that made one key as foreign like in this one plain is not depend on the order. But the order depends on the plan.

How to get list of all objects associated with a foreign key in Django

Not super experienced with Django so I apologize if this is trivial. Say I had a category instance and I wanted to get access to all of the content objects that I have previously added to my foreign key. How would I do so?
class Organization(models.Model):
id = models.CharField(primary_key=True, max_length=200, default=uuid4, editable=False, unique=True)
name=models.CharField(max_length=200,unique=True)
phoneNumber=models.CharField(max_length=20)
logo=models.CharField(max_length=100000) # storing this as base 64 encoded
location=models.CharField(max_length=200)
class Category(models.Model):
categoryName=models.CharField(max_length=300, unique=True, primary_key=True)
associatedOrganizations=models.ForeignKey(Organization,on_delete=models.CASCADE,related_name='associatedOrgs',null=True,blank=True)
associatedContent=models.ForeignKey(Content, on_delete=models.CASCADE,related_name='associatedContent',null=True,blank=True)
associatedMeetingNotices=models.ForeignKey(MeetingNotice,on_delete=models.CASCADE,related_name='associatedMeetingNotices',null=True,blank=True)
For example:
say I had the following
healthcareCategory=models.Category.objects.get(pk="healthcare")
and I wanted to access all Organizations related to healthcare, what should I do?
This?
healthcareCategory.associatedOrganizations.all()
You are close. You may want to change that related name from associatedOrgs to be associatedorgs to follow more closely to the django coding style. Documentation on this has a few examples.
healthcare_category = Category.objects.get(pk="healthcare")
organizations = healthcare_category.associatedorgs.all()
The answer by #AMG is correct. If you had not defined a related_name for associatedOrganizations you could simply do
organizations = Organization.objects.filter(category__pk='healthcare')
But I think there is another issue. Am I correct in saying that an Organization can have only one Category, but a Category can have many Organizations?
If so, then I think the ForeignKey in your model is in the wrong place.
class Organization(models.Model):
id = models.CharField(primary_key=True, max_length=200, default=uuid4, editable=False, unique=True)
name=models.CharField(max_length=200,unique=True)
phoneNumber=models.CharField(max_length=20)
logo=models.CharField(max_length=100000) # storing this as base 64 encoded
location=models.CharField(max_length=200)
# The ForeignKey should be here:
category = ForeignKey(Category, on_delete=models.CASCADE)
class Category(models.Model):
categoryName=models.CharField(max_length=300, unique=True, primary_key=True)
# remove this
# associatedOrganizations=models.ForeignKey(Organization,on_delete=models.CASCADE,related_name='associatedOrgs',null=True,blank=True)
...
The ForeignKey is a ManyToOneField so you place it in the model that will be the many, and you link it to the model that will be the one.
Now you can find all organizations within the healthcare category like this:
organizations = Organization.objects.filter(category='healthcare')

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.

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 having multiple one many to many relations that references same model

i have a model that is having multiple many to many relation to another model it is as follows:
class Match(models.Model):
"""Model docstring"""
Match_Id = models.AutoField(primary_key=True)
Team_one = models.ManyToManyField('Team',related_name='Team one',symmetrical=False,)
Team_two = models.ManyToManyField('Team',related_name='Team two',symmetrical=False,)
stadium = models.CharField(max_length=255, blank=True)
Start_time = models.DateTimeField(auto_now_add=False, auto_now=False, blank=True, null=True)
Rafree = models.CharField(max_length=255, blank=True)
Judge = models.CharField(max_length=255, blank=True)
winner = models.ForeignKey('Team', related_name='winner',to_field='Team_Name')
updated = models.DateTimeField('update date', auto_now=True )
created = models.DateTimeField('creation date', auto_now_add=True )
what is the best way to implement model like this ?. all though django does not throw any errors when passing the model sql once syncdb is excuted it throws up errors saying there is no unique constraint matching given keys
Are you sure Team_one and Team_two should be ManyToMany fields? Surely, a match only has a single team on each side - in which case these should both be ForeignKeys.
Using spaces in related_name attribute makes me uneasy, but I think the real problem is connected to the use of to_field attribute on the winner field. As far as I know you can set database relations only to unique fields. It doesn't really make sense to relate to another object using a field that may not be unique.
I'm not sure what do you want to achieve by connecting through this particular field. You usually connect models using primary key fields. This still allows you to access any other field on the related object.

Categories

Resources