I have a following django models:
class Entity(models.Model):
name = models.CharField(max_length=255)
class EntityProp(models.Model):
entity = models.ForeignKey('Entity')
key = models.CharField(max_length=255)
value = models.CharField(max_length=255, blank=True, default='')
I want to make a unique key for Entity that includes name and related EntityProp. For example, I want two entities with the same name and different set of related EntityProp instances to be different. But I want to keep the same Entity if they have identical names and EntityProp instances. Is there an elegant way to do it in Django?
As a reserve way I can create an additional field in Entity called props_hash that contains a hash of the identifiers of all related instances, but it wouldn't be easy to support such structure, I think. So I believe there's a better way.
Here you go
class Entity(models.Model):
name = models.CharField(max_length=255)
class EntityProp(models.Model):
entity = models.ForeignKey('Entity')
key = models.CharField(max_length=255)
value = models.CharField(max_length=255, blank=True, default='')
class Meta:
unique_together = ('key', 'entity')
Source: https://docs.djangoproject.com/en/dev/ref/models/options/#unique-together
Related
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.
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')
Let me start by stating that I have looked at django-polymorphic for this and still have questions. I have item models and many subtypes for items. Currently, my models look like this.
class Item(models.Model):
pass
class Television(Item):
upc = models.CharField(max_length=12, null=True)
title = models.CharField(max_length=255, null=True)
brand = models.ForeignKey(Brand)
screen_size = models.IntegerField()
class Fridge(Item):
upc = models.CharField(max_length=12, null=True)
title = models.CharField(max_length=255, null=True)
brand = models.ForeignKey(Brand)
stuff_about_fridge = models.CharField(max_length=255, null=True)
I did this at first because then I wouldn't worry about all of the left joins when querying different item types that would be caused if my models looked like this:
class Item(models.Model):
upc = models.CharField(max_length=12, null=True)
title = models.CharField(max_length=255, null=True)
brand = models.ForeignKey(Brand)
class Television(Item):
screen_size = models.IntegerField()
class Fridge(Item):
stuff_about_fridge = models.CharField(max_length=255, null=True)
I am now reaching a point where I realize that I very often query all of the Item models together and have to left join information from the subtypes instead, so I am not really saving myself there. My question is, even if I used something like django-polymorphic, would it make sense to A) put everything that is shared in the parent model and just specific things in the child models or to B) have it like I do where everything is in the child model, but they share a parent model PK just so that they can be queried together?
"Abstract base classes are useful when you want to put some common information into a number of other models. This model will then not be used to create any database table. Instead, when it is used as a base class for other models, its fields will be added to those of the child class"
Reference: https://docs.djangoproject.com/en/3.0/topics/db/models/#abstract-base-classes
The point of using inheritance is for sharing common info as mentioned in option (A).
Django-polymorphic makes using inherited models easier, nothing more.
Reference: https://django-polymorphic.readthedocs.io/en/stable/
That means, in conclusion, option (A) is correct even though if you use Django-polymorphic.
Below method is the right approach:
class Item(models.Model):
upc = models.CharField(max_length=12, null=True)
title = models.CharField(max_length=255, null=True)
brand = models.ForeignKey(Brand)
class Television(Item):
screen_size = models.IntegerField()
class Fridge(Item):
stuff_about_fridge = models.CharField(max_length=255, null=True)
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.
I am a novice in Django and I'm learning the ropes of the admin interface. I have a model with several foreign keys. These foreign keys then reference other foreign keys. On the admin website after I register the Property model and then try to add it I am given a dropdown box for each foreign key model. However this dropdown box only lists existing foreign keys. (http://i.stack.imgur.com/e5LCu.png)
What would be great is if instead of a dropdown box there were extra fields so I could add the foreign key models as I add the property model. That way I wouldn't have to manually add foreign keys and then go back and add some more, and then go back and finally add the property data.
How can I do this? This feels like a simple enough question but after intense Googling I still can't find the answer, so I apologize in advance.
Example of two of my models:
class Address(models.Model):
state = models.ForeignKey('State')
address1 = models.CharField(max_length=200)
address2 = models.CharField(max_length=200)
city = models.CharField(max_length=200)
postal_code = models.CharField(max_length=200)
class Property(models.Model):
address = models.ForeignKey('Address', blank=True, null=True)
borrower = models.ForeignKey('Person', blank=True, null=True)
company = models.ForeignKey('Company', blank=True, null=True)
contract = models.ForeignKey('Contract', blank=True, null=True)
loan_balance = models.IntegerField()
name = models.CharField(max_length=200)
primary_email = models.CharField(max_length=200)
primary_phone = models.CharField(max_length=200)
property_no = models.IntegerField()
Example of my admin.py:
# Register your models here.
class PropertyAdmin(admin.StackedInline):
model = Property
class PersonAdmin(admin.StackedInline):
model = Person
class CompanyAdmin(admin.StackedInline):
model = Company
class ContractAdmin(admin.StackedInline):
model = Contract
class CompletePropertyAdmin(admin.ModelAdmin):
inlines = [PropertyAdmin, PersonAdmin, CompanyAdmin, ContractAdmin]
admin.site.register(Property)
One solution to the problem can be, to create a custom form with fields from both the models and at the time of saving the values, first create the instance of Address model and then with that instance save your final Property model.