Rohan
Rohan

Reputation: 60

Nested Relationship in django rest framework

Please help me out of this django REST framework issue .I am trying to create on rest api which which will populate data in two tables based on argument passed .

My models look like .

class WorkloadType(models.Model):

    type = models.CharField(max_length=60)
    status = models.BooleanField(default=True)


class Workload(models.Model):

    workload_type =  models.ForeignKey(WorkloadType)
    workload_group = models.IntegerField(blank=True, null=True)
    name = models.CharField(max_length = 60)
    hdd_gb = models.IntegerField(blank=True, null=True)
    ssd_gb = models.IntegerField(blank=True, null=True)
    iops = models.CharField(max_length = 60)
    vcpu  = models.IntegerField(blank=True, null=True)
    cpu = models.IntegerField(blank=True, null=True)
    created_date = models.DateTimeField(auto_now_add=True, blank=True)
    status = models.BooleanField(default=True)

class VdiWorkload(models.Model):

    workload = models.ForeignKey(Workload)
    provision_type = models.CharField(max_length = 60)
    number_of_users = models.IntegerField()
    json_data =  models.CharField(max_length=255,blank = True,null = True)
    status = models.BooleanField(default=True)
    created_date = models.DateTimeField(auto_now_add=True, blank=True) 

I have my serializer.py file which is looking like .

from django.forms import widgets
from rest_framework import serializers
from models import WorkloadType,Workload, \
    VdiWorkload,DbWorkload,\
    VmWorkload,ExchangeWorkload,RawWorkload
class VdiSerializer(serializers.Serializer):


    class Meta:
        model = VdiWorkload


class WorkloadSerializer(serializers.Serializer):

    vdi = VdiSerializer(required = False)
    pk = serializers.IntegerField(read_only=True)
    workload_group =  serializers.IntegerField(required=False)
    workload_type = serializers.CharField(max_length = 10)
    name = serializers.CharField(max_length = 60)
    hdd_gb = serializers.IntegerField()
    ssd_gb = serializers.IntegerField()
    iops = serializers.CharField(max_length = 60)
    vcpu  = serializers.IntegerField()
    cpu = serializers.IntegerField()

    class Meta:
        model = Workload
        fields = ('vdi','workload_group','workload_type','name','hdd_gb','ssd_gb','iops','vcpu','cpu')

    def create(self, validated_data):
        """
        Create and return a new `Workload` instance, given the validated data.
        """

        wt = WorkloadType.objects.get(type = validated_data['workload_type'])
        validated_data['workload_type'] = wt
        print "=-=-=-=-=-=-=-=-=-=-=-=-=------"
        if not validated_data['workload_group']:
            workload_group = Workload.objects.latest('workload_group')
            validated_data['workload_group'] = workload_group
        else:
            try:
                workload_group = Workload.objects.latest('workload_group')
                validated_data['workload_group'] = workload_group + 1
            except:validated_data['workload_group']  = 1

        #try:node_exist = Workload.objects.get(name = validated_data['name'])
        #except:node_exist = None
        #if node_exist:
        #    raise  serializers.ValidationError('Node name already exist.')
        #else:
        wl = Workload.objects.create(**validated_data)
        VdiWorkload.objects.create(workload=wl, **validated_data)

        return wl

Now I passing the rest body like.

{
   "type": "Exchange",
   "iops": "22",
   "name": "another model",
   "hdd_gb": "23",
   "ssd_gb": "320",
   "hdd_count": "123",
   "ssd_count": "4",
   "memory": "123",
   "core": "114",
   "rackspace": "6",
   "vcpu":"12",
   "workload_type":"VDI",
   "workload_group":true,
  "cpu":"1",
  "vdi":[{
                 "provision_type":"user",
                 "number_of_users":"10",
                 "json_data":"any extra data which we want"
             }]

}

But whenever I am making post request I am getting the error

Traceback

raceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/csrf.py" in wrapped_view
77. return view_func(*args, **kwargs)
File "/home/rohit/workspace/sizer/src/sizer/Workload/views.py" in workload_list
49. serializer.save()
File "/usr/local/lib/python2.7/dist-packages/rest_framework/serializers.py" in save
164. self.instance = self.create(validated_data)
File "/home/rohit/workspace/sizer/src/sizer/Workload/WorkloadSerializer.py" in create
63. return Workload.objects.create(**validated_data)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py" in create
137. return self.get_query_set().create(**kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py" in create
375. obj = self.model(**kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py" in __init__
367. raise TypeError("'%s' is an invalid keyword argument for this function" % kwargs.keys()[0])

Exception Type: TypeError at /workload/workloadlist/
Exception Value: 'vdi' is an invalid keyword argument for this functi

Please do let me know if you need any other info I am still not able to solve out this question .

I am not able to identify this issue as I am new in DRF .

Please do let me know what might I am doing wrong here .My views looklike .

@csrf_exempt
def workload_list(request):
    """
    List all code users, or create a new user.
    """
    print "Herer I am *****************************111111"
    if request.method == 'GET':
        print "Herer I am *****************************"
        workloads = Workload.objects.all()
        serializer = WorkloadSerializer(workloads, many=True)
        return JSONResponse(serializer.data)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = WorkloadSerializer(data=data)
        print serializer
        print "****************** I am in ***********views now "
        if serializer.is_valid():
            serializer.save()
            return JSONResponse(serializer.data, status=201)
        return JSONResponse(serializer.errors, status=400)

Upvotes: 0

Views: 1424

Answers (1)

moorecm
moorecm

Reputation: 359

Forgive me if this is off track but it looks to me like the model doesn't know anything about the nested field (vdi). Did you try popping it off validated_data?

Here's a small (untested) example of what I have been working on using djangorestframework==3.1.3 with Django==1.7.

models.py:

class Child(models.Model):
    child_data = models.CharField(max_length=255)

class Parent(models.Model):
    # Set 'related_name' to the nested field name in the serializer.
    child_id = models.ForeignKey(Child, related_name='child')

serializers.py:

class ChildSerializer(serializers.ModelSerializer):
    class Meta:
        model = Child

class ParentSerializer(serializers.ModelSerializer):
    # The ForeignKey in the model is supplied with this name so that GET
    # requests can populate this and the source field below makes it
    # accessible in create after validation.
    child = TestInfoSerializer(source='child_id')

    class Meta:
        model = Parent
    fields = ('child', )

    def create(self, validated_data):
        child_data = validated_data.pop('child_id')  # strip out child_id for subsequent Parent create
        try:
            # try to find an existing row to fulfill the foreign key
            child_instance = Child.objects.filter(**child_data)[0]
        except IndexError:
            # create a new row
            child_instance = Child.objects.create(**child_data)
        return Parent.objects.create(child_id=child_instance, **validated_data)

With this I can POST nested JSON without thinking about the foreign key:

{
    "child": {
        "child_data": "asdf"
    }
}

GET also returns the nested representation with this setup.

I hope this helps.

Upvotes: 1

Related Questions