抽象模型中的ManyToManyField及其through选项

6 投票
2 回答
2707 浏览
提问于 2025-04-17 10:46

这里有个有趣的问题.. 我把模型简化了一下,方便理解..

class Participant(Person):
    passport_number = models.IntegerField(verbose_name=_('Passport Number'), db_column=u'PassportNumber')

    class Meta:
        db_table = u'Participant'

class Journey(BaseModel):
    participants = models.ManyToManyField(Participant, related_name='%(app_label)s_%(class)s_participants', through=u'ParticipantJourney')

    class Meta:
        abstract = True

class PlaneJourney(Journey):
    flight_number = models.CharField(max_length=16, verbose_name=_('Flight Number'), db_column=u'FlightNumber')

    class Meta:
        db_table = u'PlaneJourney'

class ParticipantJourney(BaseModel):
    participant = models.ForeignKey(Participant, verbose_name=_('Participant'), db_column=u'ParticipantId')

    journey_content_type = models.ForeignKey(ContentType, related_name='journey_content_type')
    journey_object_id = models.PositiveIntegerField()
    journey = generic.GenericForeignKey('journey_content_type', 'journey_object_id') # models.ForeignKey(Journey, verbose_name=_('Journey'), db_column=u'JourneyId')

    payment_content_type = models.ForeignKey(ContentType, related_name='payment_content_type')
    payment_object_id = models.PositiveIntegerField()
    payment = generic.GenericForeignKey('payment_content_type', 'payment_object_id') # models.ForeignKey(Payment, verbose_name=_('Payment'), db_column=u'PaymentId')

    class Meta:
        db_table = u'ParticipantJourney'

ParticipantJourney模型是用来把参与者和旅程联系起来的。这里的旅程是个抽象概念,因为它可以通过不同的交通方式来完成,每种交通方式都有自己特定的字段。我觉得这个设置是对的,但我遇到了以下错误信息:

错误:一个或多个模型没有通过验证: kandersteg.planejourney: 'participants' 是通过模型ParticipantJourney手动定义的多对多关系,但它没有指向Participant和PlaneJourney的外键

我需要保留这个手动定义的链接表,因为我还想把支付信息和旅程关联起来,所以我不知道接下来该怎么做。如果有人能帮我解答一下,我将非常感激!

谢谢, Alex

2 个回答

0

你可以尝试把Journey定义为一个具体的类,而不是抽象类,但这样的话数据就会分散在多个表格里。

我在这里发现了一些有趣的内容: https://stackoverflow.com/a/3821384/1156004

3

Django不把通用外键当作通过模型中必需的外键,目前也没有办法在抽象基类中定义一个带有通过模型的多对多关系。

不过,Django中有一个功能请求(ticket #11760),希望能让你在通过字段中使用%(class)s,比如在Journey模型中使用through='Pariticipant_%(class)s'。这样的话,你需要为每个Journey的子类手动创建通过表。但正如我所说,这个功能请求目前还只是个开放的提议。

撰写回答