My models.py

from django.db import models
from netfields import InetAddressField, CidrAddressField, NetManager

class IP(models.Model):
    """
        Stores IP Objects
    """
    # name is the reverse lookup of an IP if it exists else it is IP_<value>
    name = models.CharField(max_length=50, unique=True)
    value = InetAddressField(unique=True)

    objects = NetManager()

    def __unicode__(self):
        return f'{self.name}'


class CIDR(models.Model):
    """
        Stores CIDR Objects
    """
    # name of a subnet is NETWORK_<value>
    name = models.CharField(max_length=50, unique=True)
    value = CidrAddressField(unique=True)

    objects = NetManager()

    def __unicode__(self):
        return f'{self.name}'


class IPGroup(models.Model):
    """
        Stores IP Groups
    """
    name = models.CharField(max_length=50, unique=True)
    ips = models.ManyToManyField(IP, through=IPGroupToIP)
    cidrs = models.ManyToManyField(CIDR, through=IPGroupToCIDR)

    def __unicode__(self):
        return f'{self.name}'


My serializers.py

class IPSerializer(serializers.ModelSerializer):
    class Meta:
        model = IP
        fields = ['id', 'name', 'value']


class CIDRSerializer(serializers.ModelSerializer):
    class Meta:
        model = CIDR
        fields = ['id', 'name', 'value']


class IPGroupSerializer(serializers.ModelSerializer):
    """
        This Serializer is responsible for parsing IPGroup POST Request.
        It validates the JSON Body and throws error if any of the fields does 
not meet requirements.
    """
    ips = IPSerializer(many=True)
    cidrs = CIDRSerializer(many=True)

    class Meta:
        model = IPGroup
        depth = 1
        fields = '__all__'

    def validate(self, data):
        mandatory_list = ['ips', 'cidrs']
        if not any(data[item] for item in mandatory_list):
            raise serializers.ValidationError("Atleast one of the fields(IP, 
Subnets) should be present")

        if ' ' in data['name']:
            raise serializers.ValidationError("IPGroups cannot have spaces in 
their names")

        return data

    @transaction.atomic()
    def create(self, validated_data):
        # Pop out ips, subnet since these are M2M and have to be created 
separately
        ips_data = validated_data.pop('ips', None)
        cidrs_data = validated_data.pop('cidrs', None)

        # First create an IPGroup with the required name
        ip_group = IPGroup.objects.create(name=validated_data['name'])

        # Now create the M2M relationships
        if ips_data:
            for ip in ips_data:
                # Get the ip object id if already created or create it on the 
fly and save it
                ip_obj, created = IP.objects.get_or_create(name=ip['name'], 
value=ip['value'])
                IPGroupToIP.objects.create(ip_group_id=ip_group.id, 
ip_id=ip_obj.id)

        if cidrs_data:
            for cidr in cidrs_data:
                # Get the subnet object id if already created or create it on 
the fly and save it
                cidr_obj, created = 
CIDR.objects.get_or_create(name=f"NETWORK_{cidr['name']}", value=cidr['value'])
                IPGroupToCIDR.objects.create(ip_group_id=ip_group.id, 
cidr_id=cidr_obj.id)

        return ip_group



My views.py

class IPGroupCreateView(generics.CreateAPIView):
    queryset = IPGroup.objects.get_queryset()
    serializer_class = IPGroupSerializer


This however keeps giving me a validation error saying that IP or CIDR 
already exists. However, I am using the get_or_create to create IPs and 
CIDRs and hence should not be getting this error. I am assuming that this 
happening 
because of the nested model serializer's unique field validation kicking 
in. How would I disable the unique key validation for IPs and CIDRs only 
when i am creating an IPGroup ?

-- 
You received this message because you are subscribed to the Google Groups 
"Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to