Amirgem
Amirgem

Reputation: 161

Django Rest Framework, updating nested serialized data

I'm new to using the Django Rest Framework and serialized data, I'm trying to update a nested serializer but ran into a wall, I've looked around but most people have problems in the serializers.py side while I can't even get into def update without an error, these are my classes:

Views.py

from django.shortcuts import render
from rest_framework import generics
from api.serializers import ProfileSerializer
from django.contrib.auth.models import User
from api.models import Profile
from django.http import JsonResponse

class ProfileView(generics.ListCreateAPIView):
    def get(self, request):
        profile = Profile.objects.filter(user_id=request.user.id)
        serializer = ProfileSerializer(profile, many=True)
        return JsonResponse(serializer.data, safe=False)
    def post(self, request, *args, **kwargs):
        profile = Profile.objects.filter(user_id=request.user.id)
        data = request.POST
        serializer = ProfileSerializer(profile, data=data, partial=True)
        if serializer.is_valid():
            serializer.save()
        else:
            print(serializer.errors)
        return JsonResponse(serializer.data, safe=False)

Serializers.py

from rest_framework import serializers
from django.contrib.auth.models import User
from api.models import Profile

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id','username','first_name','last_name','email','last_login','date_joined','is_active')

class ProfileSerializer(serializers.ModelSerializer):
    user = UserSerializer()
    class Meta:
        model = Profile
        fields = ('id','phone','birth_date','user')

        def update(self, instance, validated_data):
            #Cant get here
            print("hey")
            return instance

Sample structure

[
    {
        "id": 3,
        "phone": "XXXXXX",
        "birth_date": "2017-06-29",
        "user": {
            "id": 1,
            "username": "xxxxx",
            "first_name": "XXXXX",
            "last_name": "XXXX",
            "email": "[email protected]",
            "last_login": "2017-06-29T15:16:11.438818Z",
            "date_joined": "2017-06-23T16:48:38Z",
            "is_active": true
        }
    }
]

My current error: (Post Data: phone = 0000000)

AttributeError at /profile/
'QuerySet' object has no attribute '_meta'

Thank you!

Upvotes: 4

Views: 9303

Answers (3)

AwsAnurag
AwsAnurag

Reputation: 109

I faced a similar issue and resolved it using a workaround. First let me explain my scenario. When a SUBMIT button is pressed on a JS page, it will trigger a REST API which will increment the count of an existing DB item by 1. So I parsed the contents of the incoming JSON request into a variable, say A. But since this variable was immutable, so I created a new variable say X, and then added the value in a format which could be sent to the serializable class like so:- X = {'item_name': A["item_name"], 'count_of_votes': last_count + 1} Then serializer_class_Object = serializer_class(existing_object_ref, data=X)

Upvotes: 0

StackEdd
StackEdd

Reputation: 712

Found myself in similar situation and I was able to solve as below.Hope it helps.

def update(self, instance, validated_data):
    user_data = validated_data.pop('user')
    user_serializer = UserSerializer()
    super(self.__class__, self).update(instance,validated_data)
    super(UserSerializer,user_serializer).update(instance.user,user_data)
    return instance

Upvotes: 8

neverwalkaloner
neverwalkaloner

Reputation: 47354

You see this error because you are passing queryset instead of instance to serializer __init__. To solve error change this:

def post(self, request, *args, **kwargs):
    profile = Profile.objects.filter(user_id=request.user.id)

to this:

def post(self, request, *args, **kwargs):
    profile = Profile.objects.get(user_id=request.user.id)

in other words instead of queryset, which returned by filter you need Profile instance returned by get.

UPD

to update nested user try this (didnt test it, let me know if this have any errors):

def update(self, instance, validated_data):
    user = validated_data.get('user')
    instance.user.first_name = user.get('first_name')
    instance.user.save()

    print("hey")
    return instance

Upvotes: 6

Related Questions