我正在Google Appengine上开发一个Django应用程序,我遇到了一个数据库设计问题,其中多表继承似乎是最好的解决方案。但遗憾的是,Appengine不支持多表继承,因为它需要JOIN。我正在寻找满足以下要求的替代解决方案:
**见底部的更新**
有3种不同的用户类型或配置文件:
这些配置文件共享某些属性,但也具有各自类型的唯一属性。例如,所有配置文件都有联系电子邮件和电话号码,但只有企业需要提供徽标或指定其业务类型。
此外,我需要能够从db(无论类型)检索Profile对象,并获取每个(Business,Employee或Client)的扩展或子配置文件。此外,Business,Employee或Client对象还应该能够轻松访问父配置文件。换句话说,关系需要双向工作(如profile.employee
或employee.profile
)。
到目前为止,我已经提出了两种可能的解决方案:
子模型中的OneToOneField:
class Profile(models.Model):
# Profile may exist before user claims it
user = models.OneToOneField(User, blank=True, null=True)
email ...
phone ...
... other common fields ...
class Business(models.Model):
profile = models.OneToOneField(Profile, verbose_name="user profile", related_name="biz_profile")
class Employee(models.Model):
profile = models.OneToOneField(Profile, verbose_name="user profile", related_name="employee_profile")
class Client(models.Model):
profile = models.OneToOneField(Profile, verbose_name="user profile", related_name="client_profile")
这样我就可以执行以下操作:profile.biz_profile
和biz.profile
父模型中的唯一通用外键:
class Profile(models.Model):
content_type=models.ForeignKey(ContentType)
object_id=models.PositiveIntegerField()
content_object=generic.GenericForeignKey('content_type','object_id')
email ...
phone ...
... other common fields ...
class Meta:
unique_together = ('content_type', 'object_id')
class Business(models.Model):
profiles = generic.GenericRelation(Profile)
class Employee(models.Model):
profiles = generic.GenericRelation(Profile)
class Client(models.Model):
profiles = generic.GenericRelation(Profile)
这样我就可以执行以下操作:profile.content_object
和biz.profiles.all()[0]
第一种方法(OneToOneField)似乎是最直接的,但我需要想出一个更好的方法来知道要调用哪个孩子,可能是通过在Profile模型中设置content_type来创建一个方法,如:
def get_instance(self):
# Need to look at contenttype framework, but you get the idea
if self.content_type == 'business':
return self.biz_profile
elif self.content_type == 'employee':
return self.employee_profile
elif self.content_type == 'client':
return self.client_profile
return None
我没有选择其中任何一种解决方案,所以我欢迎任何其他解决方案或对我所拥有的改进。
提前致谢!
更新
自我第一次发布以来,我的原始要求已经改变事实证明我只需要父母>子访问NOT child> parent。鉴于此,我将使用独特的通用外键方法。但是,我仍然在寻找原始问题的答案,所以如果你有解决方案,不要害羞。