I want to have an abstract Company
model in Django, and extend it depending on the type of the company involved:
class Company(models.Model):
name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
class Meta:
abstract = True
class Buyer(Company):
# Buyer fields..
pass
class Seller(Company):
# Seller fields...
pass
Every user on the system is associated with a company, so I want to add the following to the User profile:
company = models.ForeignKey('Company')
But this gives the dreaded error:
main.Profile.company: (fields.E300) Field defines a relation with model 'Company', which is either not installed, or is abstract.
So I imagine what I'm trying to do cannot be done. I saw that the contenttypes framework could be used for this purpose, as answered in this question. My issue with that is that I don't want the company
field to point to any model, but just subclasses of the Company
model.
Is there anything else I can use for this purpose?
The reason the ForeignKey
cannot reference an abstract model directly is that individual models that inherit from the abstract model actually have their own tables in the database.
Foreign keys are simply integers referencing the id from the related table, so ambiguity would be created if a foreign key was related to an abstract model. For example there might be be a Buyer
and Seller
instance each with an id of 1, and the manager would not know which one to load.
Using a generic relation solves this problem by also remembering which model you are talking about in the relationship.
It does not require any additional models, it simply uses one extra column.
Example -
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
class Foo(models.Model):
company_type = models.ForeignKey(ContentType)
company_id = models.PositiveIntegerField()
company = GenericForeignKey('company_type', 'company_id')
And then -
>>> seller = Seller.objects.create()
>>> buyer = Buyer.objects.create()
>>>
>>> foo1 = Foo.objects.create(company = seller)
>>> foo2 = Foo.objects.create(company = buyer)
>>>
>>> foo1.company
<Seller: Seller object>
>>> foo2.company
<Buyer: Buyer object>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With