Die Datenbank meiner App wird gefüllt und mit externen Datenquellen synchronisiert. Ich habe ein abstraktes Modell, von dem alle Modelle meiner Django 2.2-App abgeleitet sind und wie folgt definiert sind:
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")
Das object_id
Feld kann nicht als eindeutig festgelegt werden, da jede Datenquelle, die ich in meiner App verwende, möglicherweise ein Objekt mit einem enthält object_id = 1
. Daher ist es notwendig, den Ursprung des Objekts anhand des Feldes aufzuspüren object_origin
.
Leider unterstützt Djangos ORM keine Fremdschlüssel mit mehr als einer Spalte.
Problem
Während halten die automatisch generierten Primärschlüssel in der Datenbank ( id
), würde Ich mag an meinem Fremdschlüssel und viele-zu-viele Beziehungen passieren auf beiden machen object_id
und object_origin
Felder anstelle des Primärschlüssels id
.
Was ich versucht habe
Ich dachte darüber nach, so etwas zu tun:
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)
Aber Django beschwert sich darüber:
myapp.B.to_a_fk: (fields.E312) The to_field 'composed_object_origin_id' doesn't exist on the related model 'myapp.A'.
Und es klingt echt, Django hat das to_field
als Datenbankfeld angegebene Feld ausgenommen . Es ist jedoch nicht erforderlich, ein neues Feld zu meinem hinzuzufügen, CommonModel
da composed_object_type_id
es aus zwei nicht nullbaren Feldern besteht ...