Google Appengine で Django アプリケーションを開発していますが、複数テーブルの継承が最適なソリューションと思われるデータベース設計の問題に遭遇しました。残念ながら、複数テーブルの継承は JOIN を必要とするため、Appengine ではサポートされていません。次の要件を満たす代替ソリューションを探しています。
**下部の更新を参照してください**
3 つの異なるユーザー タイプまたはプロファイルがあります。
- ビジネス(すなわち所有者)
- 従業員
- クライアント
これらのプロファイルは特定の属性を共有していますが、それぞれのタイプに固有の属性も持っています。たとえば、すべてのプロファイルには連絡先の電子メールと電話番号がありますが、ロゴを提供するか、ビジネス タイプを指定する必要があるのはビジネスのみです。
さらに、(タイプに関係なく) データベースからプロファイル オブジェクトを取得し、それぞれ (ビジネス、従業員、またはクライアント) の拡張プロファイルまたは子プロファイルを取得できる必要があります。また、Business、Employee、または Client オブジェクトも、親プロファイルに簡単にアクセスできる必要があります。言い換えれば、関係は両方向 (profile.employee
またはのようにemployee.profile
) で機能する必要があります。
これまでのところ、2 つの可能な解決策を考え出しました。
子モデルの 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
私はこれらの解決策のいずれにも固執していないので、ここにあるものに対する代替の解決策または改善を歓迎します.
前もって感謝します!
更新
最初に投稿してから、元の要件が変更されました。子>親ではなく、親>子アクセスのみが必要であることがわかりました。これを考慮して、代わりに独自の Generic Foreign Key アプローチを使用します。ただし、元の質問に対する回答をまだ探しているので、解決策があれば恥ずかしがらないでください。