Django - Alternative to multi-table inheritance in Appengine

一笑奈何 提交于 2019-12-07 20:55:59

问题


I'm developing a Django application on Google Appengine, and I came across a db design problem where multi-table inheritance seems to be the best solution. Unfortunately, however, multi-table inheritance is not supported on Appengine because it requires JOINs. I'm looking for an alternative solution that meets the following requirements:

** See updates at bottom **

There are 3 different user types, or profiles:

  1. Business (i.e. owner)
  2. Employee
  3. Client

These profiles share certain attributes, but also have unique attributes for their respective types. For example, all profiles have a contact email and phone number, but only Businesses need to provide a logo or specify their business type.

In addition, I need to be able to retrieve Profile objects from the db (regardless of type), and get the extended or child profile for each (Business, Employee, or Client). Also, a Business, Employee, or Client object should also be able to access the parent profile easily. In other words, the relationship needs to work in both direction (like profile.employee or employee.profile).

So far, I have come up with two possible solutions:

OneToOneField in child model:

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")

This will allow me to do the following: profile.biz_profile and biz.profile

Unique Generic Foreign Key in parent model:

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)

This will allow me to do the following: profile.content_object and biz.profiles.all()[0]

The first approach (OneToOneField) seems the most straight forward, but I would need to come up with a better way to know which child to call, perhaps by setting the content_type in the Profile model creating a method like:

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

I'm not set on either of these solutions, so I welcome any alternative solutions or improvements to what I have here.

Thanks in advance!

UPDATE
My original requirements have changed since I first posted. It turns out I only need parent>child access NOT child>parent. In light of this, I'm going to use the unique Generic Foreign Key approach instead. However, I am still looking for an answer to the original question, so don't be shy if you have a solution.

来源:https://stackoverflow.com/questions/6431549/django-alternative-to-multi-table-inheritance-in-appengine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!