Django-rest-framework: Exception on accessing serializer.data after serizaler.is_valid() return True.

Created on 24 Nov 2012  路  7Comments  路  Source: encode/django-rest-framework

I have a following serializer:

from rest_framework import serializers
class RestaurantInfoSerializer(serializers.Serializer):
  title = serializers.CharField(required=True)
  email = serializers.CharField(required=True)
  password = serializers.CharField(required=True)
  confirm_password = serializers.CharField(required=True)
  zip = serializers.CharField(required=True)
  address = serializers.CharField(required=True)
  phone = serializers.CharField(required=True)
  contact_name = serializers.CharField(required=True)

My view is following:

    from django.template.response import TemplateResponse
    from rest_framework import generics, status
    from rest_framework.permissions import AllowAny
    from rest_framework.response import Response
    from t.serializers import RestaurantInfoSerializer


    class RestaurantRegisterView(generics.GenericAPIView):
        serializer_class = RestaurantInfoSerializer
        http_method_names = ["post", ]
        permission_classes = [AllowAny, ]

        def post(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.DATA)
            if serializer.is_valid():
                print "valid info"
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

url for it:

url('^test_ser/$', RestaurantRegisterView.as_view(), name="test_serializer"),

And i`m sending following request:

   $.post("{%   url test_serializer %}",
                          { zip: "123",
                            email: "123",
                              title: "123",
                              password: "123",
                              confirm_password: "123",
                              address: "123",
                              phone: "123",
                              contact_name: "123"
                          },
                          function(data){
                     console.log(data);
                   } );

And after sending this request i get when accessing serializer.data :

AttributeError at /test_ser/
    'str' object has no attribute 'email'

    Request Method: POST
    Request URL: http://127.0.0.1:8000/test_ser/
    Django Version: 1.4.2
    Python Executable: C:\Python27\python.exe
    Python Version: 2.7.1
    Server time: Sat, 24 Nov 2012 03:24:01 +0300
    Installed Applications:
    ('django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
     'django.contrib.sites',
     'django.contrib.messages',
     'django.contrib.staticfiles',
     't')
    Installed Middleware:
    ('django.middleware.common.CommonMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware')

    Traceback:
    File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
      111.                         response = callback(request, *callback_args, **callback_kwargs)
    File "C:\Python27\lib\site-packages\django\views\generic\base.py" in view
      48.             return self.dispatch(request, *args, **kwargs)
    File "C:\Python27\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
      77.         return view_func(*args, **kwargs)
    File "C:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
      363.             response = self.handle_exception(exc)
    File "C:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
      360.             response = handler(request, *args, **kwargs)
    File "C:\Users\ShapeR\PycharmProjects\serializertest\t\views.py" in post
      18.             return Response(serializer.data, status=status.HTTP_201_CREATED)
    File "C:\Python27\lib\site-packages\rest_framework\serializers.py" in data
      304.             self._data = self.to_native(self.object)
    File "C:\Python27\lib\site-packages\rest_framework\serializers.py" in to_native
      249.             return [self.convert_object(item) for item in obj]
    File "C:\Python27\lib\site-packages\rest_framework\serializers.py" in convert_object
      188.             value = field.field_to_native(obj, field_name)
    File "C:\Python27\lib\site-packages\rest_framework\fields.py" in field_to_native
      85.             value = getattr(obj, field_name)

    Exception Type: AttributeError at /test_ser/
    Exception Value: 'str' object has no attribute 'email'
    Request information:
    GET: No GET data

    POST:
    confirm_password = u'123'
    zip = u'123'
    title = u'123'
    phone = u'123'
    address = u'123'
    contact_name = u'123'
    password = u'123'
    email = u'123'

    FILES: No FILES data

I use 2.1.6 version but its same with 2.1.2 version.

Bug

All 7 comments

why do you use .data instead of .DATA in the view? shouldn't it be:

if serializer.is_valid():
                print "valid info"
                return Response(serializer.DATA, status=status.HTTP_201_CREATED)

No, it shouldn`t according to documentation. http://django-rest-framework.org/api-guide/serializers.html#serializing-objects
I dont know where you get .DATA

Seems valid but if you are able to reduce this to a more minimal example case that'd be v helpful.

I dont know what else can be minimized except serializer class.
I changed serializer to this:

      class RestaurantInfoSerializer(serializers.Serializer):
           some_field = serializers.CharField(required=True)

and js to this:

         $.post("{%   url test_serializer %}",
                              {
                                  some_field: "123"
                              },
                              function(data){
                         console.log(data);
                       } );

And i`m still getting error:
AttributeError at /test_ser/
'str' object has no attribute 'some_field'

just my first impression after 10 secs view....

shouldn't this:

some_field: "123"

be like this:

"some_field": "123"

No, it can be with "", but it shouldn't. Its javascript not a python.

Note: Issue was due to serializer having no restore_object method. As a result, when deserializing the data, it returns a dict, rather than instantiating an object. When the serializer later tries to serialize the result (accessing serializer.data) it blows up because it can't serialize the dict (only objects.)

REST framework now supports serializers acting on dict, as well as acting on a regular object, so this should now work as of master, and the impending 2.2 release.

Was this page helpful?
0 / 5 - 0 ratings