2

我正在 Google Appengine 上开发一个 Django 应用程序,我遇到了一个数据库设计问题,其中多表继承似乎是最好的解决方案。然而不幸的是,Appengine 不支持多表继承,因为它需要 JOIN。我正在寻找满足以下要求的替代解决方案:

** 见底部更新 **

有 3 种不同的用户类型或配置文件:

  1. 企业(即所有者)
  2. 员工
  3. 客户

这些配置文件共享某些属性,但也具有各自类型的独特属性。例如,所有个人资料都有联系电子邮件和电话号码,但只有企业需要提供徽标或指定其业务类型。

此外,我需要能够从数据库中检索 Profile 对象(无论类型如何),并获取每个(业务、员工或客户)的扩展或子配置文件。此外,Business、Employee 或 Client 对象也应该能够轻松访问父配置文件。换句话说,这种关系需要双向发挥作用(比如profile.employeeemployee.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_profilebiz.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_objectbiz.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

我对这些解决方案中的任何一个都没有设置,所以我欢迎任何替代解决方案或改进我在这里的解决方案。

提前致谢!

更新
自从我第一次发布以来,我的原始要求已经改变。事实证明我只需要父>子访问而不是子>父。鉴于此,我将改用独特的通用外键方法。但是,我仍在寻找原始问题的答案,所以如果您有解决方案,请不要害羞。

4

0 回答 0