アプリのデータベースにデータが入力され、外部データソースとの同期が維持されます。私の抽象モデルがありますDjango 2.2アプリのすべてのモデルは、次のように定義されています:
_class CommonModel(models.Model):
# Auto-generated by Django, but included in this example for clarity.
# id = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')
Origin_SOURCEA = '1'
Origin_SOURCEB = '2'
Origin_CHOICES = [
(Origin_SOURCEA, 'Source A'),
(Origin_SOURCEB, 'Source B'),
]
object_Origin = models.IntegerField(choices=Origin_CHOICES)
object_id = models.IntegerField()
class A(CommonModel):
some_stuff = models.CharField()
class B(CommonModel):
other_stuff = models.IntegerField()
to_a_fk = models.ForeignKey("myapp.A", on_delete=models.CASCADE)
class C(CommonModel):
more_stuff = models.CharField()
b_m2m = models.ManyToManyField("myapp.B")
_
_object_id
_フィールド一意として設定することはできませんアプリで使用する各データソースには、_object_id = 1
_のオブジェクトがある場合があるためです。したがって、フィールド_object_Origin
_によって、オブジェクトのオリジンを追跡する必要があります。
残念ながら、DjangoのORMは複数の列の外部キーをサポートしていません。
自動生成された主キーをデータベース(id
)に保持しながら、外部キーと多対多の関係を_object_id
_と_object_Origin
_の両方のフィールドで発生させたい主キーの代わりにid
。
私はこのようなことをすることを考えました:
_class CommonModel(models.Model):
# Auto-generated by Django, but included in this example for clarity.
# id = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')
Origin_SOURCEA = '1'
Origin_SOURCEB = '2'
Origin_CHOICES = [
(Origin_SOURCEA, 'Source A'),
(Origin_SOURCEB, 'Source B'),
]
object_Origin = models.IntegerField(choices=Origin_CHOICES)
object_id = models.IntegerField()
def _get_composed_object_Origin_id(self):
return f"{self.object_Origin}:{self.object_id}"
composed_object_Origin_id = property(_get_composed_object_Origin_id)
class A(CommonModel):
some_stuff = models.CharField()
class B(CommonModel):
other_stuff = models.IntegerField()
to_a_fk = models.ForeignKey("myapp.A", to_field="composed_object_Origin_id", on_delete=models.CASCADE)
_
しかしDjangoはそれについて不平を言う:
myapp.B.to_a_fk: (fields.E312) The to_field 'composed_object_Origin_id' doesn't exist on the related model 'myapp.A'.
Djangoは、データベースフィールドとして_to_field
_に指定されたフィールドを除きます。ただし、新しいフィールドをCommonModel
に追加する必要はありません。 _composed_object_type_id
_は2つのnull不可フィールドを使用して構築されています...
合成オブジェクトのオリジンIDを、save
で更新され、composed_object_Origin_id
として使用されるフィールド(to_field
)にすることができます。
class CommonModel(models.Model):
Origin_SOURCEA = "1"
Origin_SOURCEB = "2"
Origin_CHOICES = [
(Origin_SOURCEA, "Source A"),
(Origin_SOURCEB, "Source B"),
]
object_Origin = models.IntegerField(choices=Origin_CHOICES)
object_id = models.IntegerField()
composed_object_Origin_id = models.CharField(max_length=100, unique=True)
def save(self, **kwargs):
self.composed_object_Origin_id = f"{self.object_Origin}:{self.object_id}"
# Just in case you use `update_fields`, force inclusion of the composed object Origin ID.
# NOTE: There's definitely a less error-prone way to write this `if` statement but you get
# the Gist. e.g., this does not handle passing `update_fields=None`.
if "update_fields" in kwargs:
kwargs["update_fields"].append("composed_object_Origin_id")
super().save(**kwargs)
class A(CommonModel):
some_stuff = models.CharField(max_length=1)
class B(CommonModel):
other_stuff = models.IntegerField()
to_a_fk = models.ForeignKey(
"myapp.A", to_field="composed_object_Origin_id", on_delete=models.CASCADE
)