Django-对称关系OneToOneField

时间:2019-04-04 18:29:13

标签: django django-models

我正在编写和应用程序来管理我的网络设备。我创建了一个模型RJ45port,可以根据需要将其添加到设备中。一个RJ45端口可以插入另一个RJ45端口,并且只能插入一个。

这是我创建的模型:

class RJ45port(models.Model):
    plugged_into = models.OneToOneField('self', on_delete=models.SET_NULL, blank=True, null=True)

当我将RJ45端口“插入”另一个时,我希望第二个将“ plugged_into”设置为第一个。我希望这种关系是对称的。如果我“拔出”,我希望两个RJ45端口都将“ plugged_into”设置为null或空白。

我发现了一些代码,这可能是一个提示:

def save(self, *args, **kwargs):
    super(RJ45port, self).save()    
    self.plugged_into.plugged_into = self

说实话,我在这里有点迷路了,这是我要使此应用程序正常运行的最后一步...

3 个答案:

答案 0 :(得分:0)

最适合的是制作一个模型plug_into()方法,然后使用它来将一个实例“插入”到另一个实例以及unplug()方法。

示例:

class RJ45port(models.Model):
    plugged_into = models.OneToOneField('self', on_delete=models.SET_NULL, blank=True, null=True)

    def plug_into(self, instance):
        self.plugged_into = instance
        instance.plugged_into = self

        self.save(update_fields=['plugged_into'])
        instance.save(update_fields=['plugged_into'])
        return [self.plugged_into, instance.plugged_into]

    def unplug(self):
        self.plugged_into.plugged_into = None
        self.plugged_into = None

        self.plugged_into.save(update_fields=['plugged_into'])
        self.save(update_fields=['plugged_into'])
        return [self.plugged_into, instance.plugged_into]

然后您可以这样称呼它:

port_1 = Port.objects.all()[0]  # First port
port_2 = Port.objects.all()[1]  # Second port
port_1.plug_into(port_2)  # Should return [instance, instance]
port_1.unplug()  # Should return [None, None]

答案 1 :(得分:0)

你是对的。只需覆盖save方法。但最后请致电super().save()

class RJ45port(models.Model):
    plugged_into = models.OneToOneField('self', on_delete=models.SET_NULL, blank=True, null=True)

    def save(self, *args, **kwargs): 
        self.plugged_into.plugged_into = self
        super(RJ45port, self).save()   

答案 2 :(得分:0)

另一种选择是使用related_name,以便您可以从引用的实例进行反向访问,因此可以说该关系变为“对称”。唯一的缺点是您不能使用相同的名称来引用两个连接:

class RJ45port(models.Model):
    plugged_into = models.OneToOneField('self', on_delete=models.SET_NULL, blank=True, null=True, related_name='plugged_from')

在此示例中,可以像引用实例中的任何其他字段一样查询plugged_from