Home > OS >  How do i deal with foreign key and multiple errors for Django API framework POST?
How do i deal with foreign key and multiple errors for Django API framework POST?

Time:10-06

I have the following codes:

models.py

class Device(models.Model):
    hostname = models.CharField(max_length=50, unique = True)
    ipaddr = models.GenericIPAddressField(protocol='ipv4', unique=True, verbose_name='mangement IP') ##Use for mgt_id_addr
    date_added = models.DateTimeField(default=timezone.now)
    

    def __str__(self):
        return self.hostname

class DeviceDetail(models.Model):
    
    SUBNET_CHOICES = (
    ('16','16'),
    ('17', '17'),
    ('18','18'),
    ('19','19'),
    ('20','20'),
    ('21', '21'),
    ('22', '22'),
    ('23', '23'),
    ('24', '24'),
    ('25', '25'),
    ('26', '26'),
    ('27', '27'),
    ('28', '28'),
    ('29', '29'),
    ('30', '30'),
    )

    DEV_MODS =(
        ('Catalyst 9606R', 'Catalyst 9606R'),
        ('C9300L-48T-4X', 'C9300L-48T-4X')
    )

    
    mgt_interface = models.CharField(max_length=50)
    subnetmask = models.CharField(max_length=2, choices = SUBNET_CHOICES)
    ssh_id = models.CharField(max_length=50)
    ssh_pwd = models.CharField(max_length=50)
    enable_secret = models.CharField(max_length=50)
    dev_mod=models.CharField(max_length=50, choices = DEV_MODS) ##device_model replacement
    DD2DKEY = models.ForeignKey(Device, on_delete=models.CASCADE) ##The key to link up the tables
    
    def __str__(self):
        return self.hostname

serializers.py

from rest_framework import serializers
from .models import Device, DeviceDetail

class DeviceSerializers(serializers.ModelSerializer):
    class Meta:
        model=Device
        fields = '__all__'

class DeviceDetailSerializers(serializers.ModelSerializer):
    class Meta:
        model = DeviceDetail
        fields = ['mgt_interface', 'subnetmask', 'ssh_id', 'ssh_pwd', 'enable_secret', 'dev_mod']

views.py

@api_view(['POST'])
def create_device(request):
    device = Device()
    devicedetail = DeviceDetail()
    deviceserializer = DeviceSerializers(device, data = request.data)
    devdserializer = DeviceDetailSerializers(devicedetail, data = request.data)
    if deviceserializer.is_valid() and devdserializer.is_valid():   
        deviceserializer.save()
        devdserializer.save(DD2DKEY=deviceserializer.id)                
        results = {
        "device":deviceserializer.data,
        "device_details" : devdserializer.data,
        }
        return Response(results, status=status.HTTP_201_CREATED)
    else:
        errors = {
            "device":deviceserializer.errors,
            "device_details" : devdserializer.errors,
        }
        return Response(errors, status=status.HTTP_400_BAD_REQUEST)

This statement devdserializer.save(DD2DKEY=deviceserializer.id) is giving me the issue. I tried devdserializer.save(DD2DKEY=deviceserializer) also did not solve the issue. Error shown in powershell:

ValueError: Cannot assign "DeviceSerializers(<Device: Testing10>, data=<QueryDict: {'hostname': ['Testing10'], 'ipaddr': ['10.10.10.10'], 'mgt_interface': ['1'], 'subnetmask': ['16'], 'ssh_id': ['1'], 'ssh_pwd': ['1'], 'enable_secret': ['1'], 'dev_mod': ['Catalyst 9606R']}>):
    id = IntegerField(label='ID', read_only=True)
    hostname = CharField(max_length=50, validators=[<UniqueValidator(queryset=Device.objects.all())>])
    ipaddr = IPAddressField(label='Mangement IP', validators=[<function validate_ipv4_address>, <UniqueValidator(queryset=Device.objects.all())>])
    date_added = DateTimeField(required=False)": "DeviceDetail.DD2DKEY" must be a "Device" instance.

Another problem I am facing is the errors, I dont know why but the output of powershell shows the following error when i already called the function of is.valid() in the if statement:

AssertionError: You must call `.is_valid()` before accessing `.errors`.

CodePudding user response:

you must pass Device instance rather than device serializer instance: so this part of the code is wrong

deviceserializer.save()
devdserializer.save(DD2DKEY=deviceserializer.id)

change it to

device_instance = deviceserializer.save()
devdserializer.save(DD2DKEY=device_instance)

the serializer .save() return model instance for you and can use it.

  • Related