Arjun Nambiar
2018-08-16 19:02:02 UTC
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 ?
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 django-rest-framework+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
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 django-rest-framework+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.