How can I associate existing child to parent in Django

45 Views Asked by At

I trying to build an IPAM by Django. I will create the Subnet model and create the IPAddress by the post_save signal.

class Subnet(models.Model):
    usage = models.CharField('Usage', max_length=40)
    vlan = models.PositiveSmallIntegerField('vlan')
    cidr = models.CharField('CIDR', max_length=18)
    gateway = models.GenericIPAddressField('Gateway')
    def __str__(self):
        return str(self.vlan) + ' ' + self.usage

class IPAddress(models.Model):
    subnet = models.ForeignKey(Subnet, on_delete=models.CASCADE, verbose_name="Subnet")
    ip = models.GenericIPAddressField('IP Address', unique=True)
    mac = models.CharField('Mac Address', max_length=17, blank=True, null=True)
    vm = models.ForeignKey(VM, on_delete=models.SET_NULL, blank=True, null=True)
    class Meta:
        indexes = [
            models.Index(fields=['ip','mac']),
            models.Index(fields=['ip'], name='vm_ip_idx'),
        ]
        verbose_name = 'IP Address'
        verbose_name_plural = 'IP Addresses'
    def __str__(self):
        return str(self.ip)

@receiver(post_save, sender=Subnet)
def create_ip(sender, instance, created, **kwargs):
    if created:
        except_ip = ["0","255"]
        for ip in ipaddress.IPv4Network(instance.cidr):
            if (str(ip) != str(instance.gateway)) and (str(ip).split('.')[-1] not in [i for i in except_ip]):
                IPAddress(subnet=instance, ip=str(ip)).save()

class VM(models.Model):
    vm_name = models.CharField('VM Name', max_length=60)
    def __str__(self):
        return str(self.vm_name)

What I want to do: I created a Subnet with CIDR 172.0.0.0/24 and will automatically create total 255 IPAddress (172.0.0.1-172.0.0.254). And now I want to attach one of the IPAddress to a VM and update the MAC address in admin page.

I tried to edit in admin.py

class VMIPAdminForm(forms.ModelForm):
    ip = forms.ModelChoiceField(queryset=IPAddress.objects.all(), empty_label="IP Address")
    mac = forms.CharField(max_length=17, required=False, label="MAC Address")

    class Meta:
        model = IPAddress
        fields = ['ip', 'mac']


class VMIPInline(admin.TabularInline):
    model = IPAddress
    form = VMIPAdminForm
    exclude = ['subnet']
    extra = 1
    fk_name = "vm"

@admin.register(VM)
class VMAdmin(admin.ModelAdmin):
    inlines = [VMIPInline]

But it will show the IPAddress with this IP Address already exists when I pick the IPAddress and type in the MAC address in the VM.

0

There are 0 best solutions below