是否 possible/sensible 自定义 Django 的自动通过表以包含其他字段...通过工厂?

Is it possible/sensible to customize Django's auto-through tables to include other fields...through-factory?

我知道 django 将有助于通过 table 为简单的多对多 table 生成一个。但是,如果您想添加有关关系的信息,则需要 'linker' 或通过 table。这个例子来自docs给出的例子:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person)
    group = models.ForeignKey(Group)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

我的设计中有几个 tables/models,例如 group,它们的主要区别在于它们的 choices 属性。我稍后会添加更多。

是否可以自定义 Django 的魔法生成什么样的 through table?如果是这样,这明智吗?

我说的是这样的:

class CharacterSkillLink(models.Model):
    character =  models.ForeignKey('NWODCharacter', related_name='%(class)s_by_skill')
    skill = models.ForeignKey('Skill', choices = SKILL_CHOICES)
    value = models.IntegerRangeField(min_value=1, max_value=5)
    speciality = models.CharField(max_length=200)

class CharacterAttributeLink(models.Model):
    character =  models.ForeignKey('NWODCharacter', related_name='%(class)s_by_skill')
    attribute = models.ForeignKey('Attribute', choices = ATTRIBUTE_CHOICES)
    value = model.IntegerRangeField(min_value=1, max_value=5

class CharacterArcanaLink(models.Model):
    character =  models.ForeignKey('Mage', related_name='%(class)s_by_skill')
    arcana = models.ForeignKey('Arcana', choices = ARCANA_CHOICES)
    value = model.IntegerRangeField(min_value=1, max_value=5

以后还会有更多类似的。如果 django 有一些方法,就像 through_field 属性一样,它会很方便,它定义了要使用的 table 上的键,应该有额外的值添加到它(例如 extra_field=value).

这是possible/sensible吗?

IMO,将字段添加到 "through" table 是许多可能用途的好模式。我不确定 Django 是否需要新的语法来处理这种情况,但是如果您认为您正在创建 lots 这些 table 和 mixing/matching 不同的 tables,也许一些抽象的混合会简化事情。例如:

class CharacterLink(models.Model):
    character =  models.ForeignKey('NWODCharacter')
    class Meta:
        abstract = True

class SkillLink(models.Model):
    skill = models.ForeignKey('Skill', choices = SKILL_CHOICES)
    class Meta:
        abstract = True

class AttributeLink(models.Model):
    attribute = models.ForeignKey('Attribute', choices = ATTRIBUTE_CHOICES)
    class Meta:
        abstract = True

class CharacterSkillLink(CharacterLink, SkillLink):
    value = models.IntegerRangeField(min_value=1, max_value=5)
    speciality = models.CharField(max_length=200)

class CharacterAttributeLink(CharacterLink, AttributeLink):
    value = model.IntegerRangeField(min_value=1, max_value=5)