私はmulti-tenantedアプリケーションに取り組んでいます。このアプリケーションでは、一部のユーザーが(管理者を介して)自分のデータフィールドを定義して、フォームで追加データを収集し、データをレポートできます。後者のビットはJSONFieldを素晴らしい選択肢ではないので、代わりに次の解決策があります:
class CustomDataField(models.Model):
"""
Abstract specification for arbitrary data fields.
Not used for holding data itself, but metadata about the fields.
"""
site = models.ForeignKey(Site, default=settings.SITE_ID)
name = models.CharField(max_length=64)
class Meta:
abstract = True
class CustomDataValue(models.Model):
"""
Abstract specification for arbitrary data.
"""
value = models.CharField(max_length=1024)
class Meta:
abstract = True
CustomDataFieldがサイトへのForeignKeyを持っていることに注意してください。各サイトには異なるカスタムデータフィールドのセットがありますが、同じデータベースを使用します。次に、さまざまな具体的なデータフィールドを次のように定義できます。
class UserCustomDataField(CustomDataField):
pass
class UserCustomDataValue(CustomDataValue):
custom_field = models.ForeignKey(UserCustomDataField)
user = models.ForeignKey(User, related_name='custom_data')
class Meta:
unique_together=(('user','custom_field'),)
これは、次の使用につながります。
custom_field = UserCustomDataField.objects.create(name='zodiac', site=my_site) #probably created in the admin
user = User.objects.create(username='foo')
user_sign = UserCustomDataValue(custom_field=custom_field, user=user, data='Libra')
user.custom_data.add(user_sign) #actually, what does this even do?
しかし、これは、特に関連データを手動で作成し、それを具体的なモデルに関連付ける必要があるため、非常に不格好です。より良いアプローチはありますか?
先制的に破棄されたオプション:
Django-dynamoのアイデアをさらに推し進めています。プロジェクトはまだ文書化されていませんが、 https://github.com/charettes/Django-mutant でコードを読むことができます。
実際には、FKおよびM2Mフィールド(contrib.relatedを参照)も機能し、独自のカスタムフィールドのラッパーを定義することも可能です。
Unique_togetherやordering plus Model baseなどのモデルオプションもサポートされているため、モデルプロキシ、抽象、またはミックスインをサブクラス化できます。
実際には、メモリ内ではないロックメカニズムに取り組んで、古い定義を使用してモデル定義を複数のDjango実行インスタンス間で共有できるようにします。
このプロジェクトはまだ非常にアルファ版ですが、私のプロジェクトの基盤技術であるため、本番環境に持っていく必要があります。大きな計画ではDjango-nonrelもサポートしているため、mongodbドライバーを活用できます。
さらなる調査により、これは エンティティ属性値 デザインパターンのやや特殊なケースであり、Djangoに対していくつかのパッケージによって実装されていることが明らかになりました。
まず、元の eav-Django プロジェクトがあります。これはPyPiにあります。
第二に、最初のプロジェクトのより最近のフォーク、 Django-eav があります。これは主に、Django自身のモデルまたはサードパーティアプリのモデルでEAVを使用できるようにするリファクタリングです。