2012-10-30 31 views
6

我有一个系统模型,和一个接口模型。接口是两个系统之间的组合。之前,这个界面被表示为一个Excel工作表(交叉表)。现在我想将它存储在数据库中。Django十字表模型结构

我试着创建一个接口模型,其中两个外键给System。这不起作用,因为:

  • 它创建在目标模式两种不同的反向关系
  • 它不会避免重复(第一和第二相对交换)

我用这个代码:

class SystemInterface(Interface): 
    assigned_to = models.ManyToManyField(User) 
    first_system = models.ForeignKey(System) 
    second_system = models.ForeignKey(System) 

难道还有更好的方法吗?

我需要有对称关系:它应该很重要的是系统是接口中的“第一”或“第二”。

+0

其中的层次结构是第一个,哪个是您的第二个系统问题?或者与两个系统的关系很重要? – jondykeman

+0

不,这没关系。我希望这种关系是对称的。 first = a; second = b应该相当于first = b; second = a – pistache

+0

您能解释一下“它在目标模型上创建两种不同的反向关系”是什么意思? – stellarchariot

回答

4

我认为代表这些模型的最佳simpliest会是这样:

class System(models.Model): 
    pass 

class Interface(models.Model): 
    assigned_to = models.ManyToManyField(to=User) 
    system = models.ForeignKey(System) 

    @property 
    def systems(self): 
     Interface.objects.get(system=self.system).interfacedsystem_set.all()   

class InterfacedSystem(models.Model): 
    interface = models.ForeignKey(Interface) 
    system = models.ForeignKey(System) 

接口系统的添加/删除显然是作为练习留给读者,就把应该是相当容易。

+0

这是非常有趣的答案,我会更精确地看看它,然后回复你。谢谢 – pistache

+0

看起来没问题,直到现在:)谢谢 – pistache

2

您可以使用多对多关系with extra fields,但它不能是symetrical

用于多对多关系的表格包含两个模型之间的每个关系的一行。用于从系统到自身的多对多关系的表格在两个系统之间每个关系具有一行。这与您的模型符合用于ManyToManyField.through的模型的结构一致。

使用中间模型允许将像assign_to这样的字段添加到多对多表中。

这可能是棘手的理解,但应防止系统界面中创建(left_system = system_ 一个,right_system = system_ b)。请注意,为了表示具有“左”侧和“右”侧的多对多关系行/实例,我将“第一”改为“左”,将“第二”改为“右”。

因为它们不能是对称的,这将不能解决具有一个系统界面中的问题(left_system = system_ 一个,right_system = system_ b)和一个与系统界面中(left_system = system_ b, right_system = system_ a)。您应该防止发生在SystemInterface的clean() method中 - 或用于使用ManyToManyField.through模型来表示多对多表的任何模型。

+0

从和到什么型号? – pistache

+0

系统自我,你读过的链接? – jpic

+0

对不起,我看不出有什么可以帮助我。接口只在两个系统之间,而不是更多。 – pistache

2

由于django不支持与额外数据对称的多对多关系,因此您可能需要自行强制执行此操作。

如果您在系统中拥有方便的不可变值(例如系统ID),您可以创建一个可预测的算法,系统将存储在表中的哪个条目中。如果系统在创建Interface对象时始终保持不变,则可以使用主键。

然后,编写一个函数来创建接口。例如:

class System(models.Model): 
def addInterface(self, other_system, user): 
    system_interface = SystemInterface() 
    system_interface.assigned_to = user 
    if other_system.id < self.id: 
     system_interface.first_system = other_system 
     system_interface.second_system = self 
    else: 
     system_interface.first_system = self 
     system_interface.second_system = other_system 
    system_interface.save() 
    return system_interface 

使用这种设计,你可以做平常的验证,重复检测,等系统界面中的对象。重点是您在代码中执行约束,而不是在数据模型中。

这是否有意义?

+0

它的确如此,无论如何,如果我没有找到其他的东西,我会怎么做。但是,在SystemInterface管理器中使用此代码不是更好吗?因为使用你的方式,我将无法有效地使用管理界面。 – pistache