encode / django-rest-framework

Web APIs for Django. 🎸
https://www.django-rest-framework.org
Other
28.45k stars 6.84k forks source link

assertion error on renderers/get_raw_data_form() #2440

Closed umutbozkurt closed 9 years ago

umutbozkurt commented 9 years ago

On renderers.py, get_raw_data_form() raises assertion error with following message:

When a serializer is passed a data keyword argument you must call .is_valid() before attempting to > access the serialized .data representation. You should either call .is_valid() first, or access .initial_data instead.

Which is raised by .data property of serializer. This breaks the browsable API. On get_raw_data_form() L:626, serializer is initialized with no initial data, and on line 633 serializer.data is called, which raises an assertion error.

Versions effected 3.0.2, 3.0.3.

Further details:

class UserList(ListCreateAPIView):
    serializer_class = UserSerializer
    queryset = User.objects.all()
class UserSerializer(DocumentSerializer):
    class Meta:
        model = User
        depth = 2

Request: GET

Environment:

Request Method: GET
Request URL: http://127.0.0.1:8000/users/

Django Version: 1.7
Python Version: 2.7.6
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'rest_framework',
 'rest_framework_mongoengine',
 'BlogApp')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware')

Traceback:
File "/Library/Python/2.7/site-packages/django/core/handlers/base.py" in get_response
  137.                 response = response.render()
File "/Library/Python/2.7/site-packages/django/template/response.py" in render
  103.             self.content = self.rendered_content
File "/Library/Python/2.7/site-packages/rest_framework/response.py" in rendered_content
  59.         ret = renderer.render(self.data, media_type, context)
File "/Library/Python/2.7/site-packages/rest_framework/renderers.py" in render
  733.         context = self.get_context(data, accepted_media_type, renderer_context)
File "/Library/Python/2.7/site-packages/rest_framework/renderers.py" in get_context
  683.         raw_data_post_form = self.get_raw_data_form(data, view, 'POST', request)
File "/Library/Python/2.7/site-packages/rest_framework/renderers.py" in get_raw_data_form
  633.                 content = renderer.render(serializer.data, accepted, context)
File "/Library/Python/2.7/site-packages/rest_framework/serializers.py" in data
  463.         ret = super(Serializer, self).data
File "/Library/Python/2.7/site-packages/rest_framework/serializers.py" in data
  208.             raise AssertionError(msg)

Exception Type: AssertionError at /users/
Exception Value: When a serializer is passed a `data` keyword argument you must call `.is_valid()` before attempting to access the serialized `.data` representation.
You should either call `.is_valid()` first, or access `.initial_data` instead.
umutbozkurt commented 9 years ago

Note: same request with format=json works perfectly

xordoquy commented 9 years ago

Works here if I replace the DocumentSerializer by ModelSerializer. Sample project available at https://github.com/linovia/basic-drf-project

tweiand-10m2 commented 9 years ago

Put a possible fix in: https://github.com/umutbozkurt/django-rest-framework-mongoengine/issues/62

I will have to wait for the maintainer to let me know if it is a correct solution.

umutbozkurt commented 9 years ago

It is fixed, thanks @tweiand-10m2

naelmusleh commented 8 years ago

I am having the same issue with DRF version 3.3.0. Has this been fixed or is there a workaround?

xordoquy commented 8 years ago

Don't use 3.3.0, it has a bug that affects the browsable API. If there's still a bug please try to isolate a test case out of it so someone else can reproduce - even better if it's a DRF test case.

naelmusleh commented 8 years ago

I tried versions 3.0.1+. The only one that worked was 3.0.1 but it breaks a lot of other things that I need from more recent versions. 3.0.2+ still cause an issue.

What we are doing is the following:

sections = self.data.exam.section_set.all()
sections_json = renderer.render(serializers.TakeSectionSerializer(
            sections, self.data.user.id, many=True).data) 

If I change it to check is_valid first:

sections = self.data.exam.section_set.all()
if serializers.TakeSectionSerializer(sections, self.data.user.id, many=True).is_valid(raise_exception=True):
   sections_json = renderer.render(serializers.TakeSectionSerializer(
                sections, self.data.user.id, many=True).data)

I get the following error from is_valid():

Environment:

Request Method: GET
Request URL: http://localhost:8000/sat/477/208/bubble/

Django Version: 1.8.3
Python Version: 2.7.3
Installed Applications:
('chalktalk.apps.users',
 'chalktalk.apps.courses',
 'chalktalk.apps.exams',
 'chalktalk.apps.exams_sat',
 'chalktalk.apps.tags',
 'chalktalk.apps.lessons',
 'chalktalk.apps.practice',
 'chalktalk.apps.scoring',
 'chalktalk.apps.payment',
 'chalktalk.pages',
 'chalktalk.shared',
 'django.contrib.auth',
 'django.contrib.admin',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'compressor',
 'guardian',
 'treebeard',
 'rest_framework',
 'ckeditor',
 'django_countries',
 'passwords',
 'debug_toolbar.apps.DebugToolbarConfig')
Installed Middleware:
(u'debug_toolbar.middleware.DebugToolbarMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'chalktalk.shared.middleware.DefaultCacheControlMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'chalktalk.shared.middleware.ActiveUserControlMiddleware')

Traceback:
File "/home/vagrant/.virtualenvs/chalktalk-legacy/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/vagrant/.virtualenvs/chalktalk-legacy/local/lib/python2.7/site-packages/django/utils/decorators.py" in inner
  145.                     return func(*args, **kwargs)
File "/home/vagrant/.virtualenvs/chalktalk-legacy/local/lib/python2.7/site-packages/django/views/generic/base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)
File "/home/vagrant/.virtualenvs/chalktalk-legacy/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
  34.             return bound_func(*args, **kwargs)
File "/home/vagrant/.virtualenvs/chalktalk-legacy/local/lib/python2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  22.                 return view_func(request, *args, **kwargs)
File "/home/vagrant/.virtualenvs/chalktalk-legacy/local/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
  30.                 return func.__get__(self, type(self))(*args2, **kwargs2)
File "/vagrant/Devel/chalktalk-legacy/chalktalk/chalktalk/shared/view_utils.py" in dispatch
  21.         return super(CheckPermissionsMixin, self).dispatch(request, *args, **kwargs)
File "/home/vagrant/.virtualenvs/chalktalk-legacy/local/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
  89.         return handler(request, *args, **kwargs)
File "/home/vagrant/.virtualenvs/chalktalk-legacy/local/lib/python2.7/site-packages/django/views/generic/base.py" in get
  158.         context = self.get_context_data(**kwargs)
File "/vagrant/Devel/chalktalk-legacy/chalktalk/chalktalk/apps/exams_sat/views_take.py" in get_context_data
  508.             sections, self.data.user.id, many=True).is_valid(raise_exception=True):
File "/home/vagrant/.virtualenvs/chalktalk-legacy/local/lib/python2.7/site-packages/rest_framework/serializers.py" in is_valid
  221.             raise ValidationError(self.errors)

Exception Type: ValidationError at /sat/477/208/bubble/
Exception Value: {u'non_field_errors': [u'Expected a list of items but got type "int".']}
xordoquy commented 8 years ago

This looks like a dev error in the arguments while calling the serializer.

xordoquy commented 8 years ago

note that it's really different from the original issue.

key-er commented 7 years ago

Using djangorestframework version 3.6.2 and notice similar error i.e. "AssertionError: You must call .is_valid() before accessing .validated_data." Does the issue still exist and need to downgrade?

xordoquy commented 7 years ago

@key-er your error is the normal behavior when accessing validated_data without calling is_valid.

key-er commented 7 years ago

@xordoquy - I did call is_valid as below from django document (reference: http://www.django-rest-framework.org/tutorial/1-serialization/)

serializer = SnippetSerializer(data=data)
serializer.is_valid()
serializer.validated_data
serializer.save()
xordoquy commented 7 years ago

And this doesn't work if your data are not valid.