简体   繁体   中英

Django REST framework: Update gives error with nested serializer

I have two models

Auth User model and UserProfile

UseProfile is:

class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name='profile')
    name = models.CharField(_lazy(u'Name'), max_length=255)

For which I am using these serializers:

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

from oneanddone.users.models import UserProfile

    class UserProfileSerializer(serializers.ModelSerializer):

        class Meta:
            model = UserProfile
            fields = ('name',)


    class UserSerializer(serializers.ModelSerializer):
        profile = serializers.RelatedField()

        class Meta:
            model = User
            fields = ('id', 'username', 'email', 'groups', 'profile')

The views for both serializers are:

class UserListAPI(generics.ListCreateAPIView):
    """
    API endpoint used to get a complete list of users
    and create a new user.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer


class UserDetailAPI(generics.RetrieveUpdateDestroyAPIView):
    """
    API endpoint used to get, update and delete user data.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_field = 'email'

The nested serializer works fine for create/delete queries but for an update query like:

pdata = {"username":"testusername", "email":"test@testmail.com","profile":[{"name":"Changed Name"}]}

requests.patch('http://localhost:8000/api/v1/user/test@testmail.com/',data=json.dumps(pdata), headers={'Authorization':'Token bd876bfa04843c6ce1b82c84e27cd510f68dfbbd','Content-Type': 'application/json'}).text

I get an error saying 'UserProfile' object is not iterable. Traceback: http://pastebin.com/RA7JWFua

Can update like this be done with just nested serializer ? Please also give the custom code that I will have to add to make it work.

I got this working by making the following changes to Serializers and Views.

Serializers for both models:

from django.contrib.auth.models import User

from rest_framework import serializers

from oneanddone.users.models import UserProfile


class UserProfileSerializer(serializers.ModelSerializer):

    class Meta:
        model = UserProfile
        fields = ('name', 'username', 'privacy_policy_accepted')


class UserSerializer(serializers.ModelSerializer):
    profile = UserProfileSerializer(required=False, many=False)

    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'groups', 'profile')

Views for both serializers:

class UserDetailAPI(generics.RetrieveUpdateDestroyAPIView):
    """
    API endpoint used to get, update and delete user data.
    """
    lookup_field = 'email'
    queryset = User.objects.all()
    serializer_class = UserSerializer


class UserListAPI(generics.ListCreateAPIView):
    """
    API endpoint used to get a complete list of users
    and create a new user.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

And the update query can be written on similar lines like:

# Change Profile Data(name, username, privacy_policy_accepted)
        changed_data = {'username': 'testname', 'email': 'test@test.com',
                        'profile': {'name': 'Changed Test Name', 'username': 'testname123', 'privacy_policy_accepted': False}}
        response = self.client.patch(user_uri, changed_data, format='json')

Disclaimer: All these code snippets are now a part of an application under Mozilla organization and released under the Mozilla license.

Links to original code can be found here:

Serializers , Views , Unit Tests for Profile Update

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM