假设有一个抽象模型CarOwner:而Person或Business可以是CarOwner。此外,具有特定VIN的汽车可以属于(涉及)个人或企业,但不属于两者(互斥的情况)。在下面的代码的最后,我提出了两种可能性(参见代码中的注释“#1。我应该拥有这个???”和“#2。......或者我应该拥有这个???”)。在第一种可能性中,与抽象模型建立了多对一关系,我不确定这是否是正确的方法。在第二种情况下,建立了两种关系,我不确定这是否正确,特别是不清楚如何使它们相互排斥。那么哪一个是正确的,如果不是,请尽可能提供正确答案。谢谢。
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)
答案 0 :(得分:8)
与jproffitt提到的一样,通用关系可能是一个很好的解决方案。或者,您可以使用#2并通过创建属性并向其添加一些简单的逻辑来使其更方便:
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")
但是对于查询,您必须使用 person 或 business 。
答案 1 :(得分:3)
由于CarOwner
是抽象的,所以你不能做#1。您可以使CarOwner
具体(db表继承),然后这将起作用,但表继承带来了自己的一系列复杂性。你可以做#2或使用通用外键:
carowner_content_type = models.ForeignKey(ContentType)
carowner_object_id = models.PositiveIntegerField()
carowner = generic.GenericForeignKey('carowner_content_type', 'carowner_object_id')