Suppose there is an abstract model CarOwner: whereas a Person or a Business can be a CarOwner. In addition a Car with a certain VIN can belong (relate) to either a Person or a Business, but not both (mutually exclusive case). At the very end of the following code I presented two possibilities (see comments in the code "# 1. SHOULD I HAVE THIS???" and "# 2. ...OR SHOULD I HAVE THIS???"). In the first possibility a Many-to-One relationship is established to an abstract model and I am not sure if this is the right way. In the second case two relationships are established and I am not sure if that is correct either, especially it is not clear how to make them mutually exclusive. So which one is right and if neither, please, provide the right answer if you could. Thanks.
class CarOwner(models.Model):
location = models.CharField(max_length=50, blank=True)
class Meta:
abstract = True
class Person(CarOwner):
name = models.CharField(max_length=50, blank=True)
class Business(CarOwner):
business_id = models.CharField(max_length=50, blank=True)
class Car(models.Model):
vin = models.CharField(max_length=50, blank=True)
# 1. SHOULD I HAVE THIS??? (CarOwner is abstract)
carowner = models.ForeignKey(CarOwner, blank=True, null=True)
# 2. ...OR SHOULD I HAVE THIS???
person = models.ForeignKey(Person, blank=True, null=True)
business = models.ForeignKey(Business, blank=True, null=True)
Like jproffitt mentioned, generic relations might be a good solution for you. Alternatively you can use #2 and make it a bit more convenient by creating property and adding some simple logic to it:
class Car(models.Model):
vin = models.CharField(max_length=50, blank=True)
person = models.ForeignKey(Person, blank=True, null=True)
business = models.ForeignKey(Business, blank=True, null=True)
@property
def carowner(self):
return self.person or self.business
@carowner.setter
def carowner(self, obj):
if type(obj) == Person:
self.person = obj
self.business = None
elif type(obj) == Business:
self.business = obj
self.person = None
else:
raise ValueError("obj parameter must be an object of Business or Person class")
However for queries you'll have to use person or business.
Since CarOwner
is abstract, you cannot do #1. You could make CarOwner
concrete (db table inheritance), and then that would work, but table inheritance brings its own set of complications. You could either do #2 or use a generic foreign key:
carowner_content_type = models.ForeignKey(ContentType)
carowner_object_id = models.PositiveIntegerField()
carowner = generic.GenericForeignKey('carowner_content_type', 'carowner_object_id')
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