是否可以/合理地定制Django的自动通过表以包含其他字段...通过工厂?

时间:2015-02-02 15:26:07

标签: python django django-orm

我知道django会为简单的多对多表生成一个直通表。但是,如果要添加有关关系的信息,则需要一个“链接器”。或通过表格。 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)

我在设计中有几个表格/模型,例如group,这些表/模型大多只是choices属性。我稍后会添加更多内容。

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

我正在谈论的是:

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属性定义要使用的直通表上的键一样,应该有额外的值添加到它(例如{{extra_field=value属性。 1}})。

这可能/合理吗?

1 个答案:

答案 0 :(得分:1)

IMO,将字段添加到"至" table是许多可能用途的绝佳模式。我不确定Django是否需要新的语法来处理这种情况,但是如果你认为你正在创建这些表的 lot 并混合/匹配不同的表,那么也许一些抽象的mixin会简化事情。例如:

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)