Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

model arrayfield with float child and null True can not be serialized #3685

Closed
mikofski opened this issue Dec 1, 2015 · 4 comments
Closed

Comments

@mikofski
Copy link

mikofski commented Dec 1, 2015

DRF: 3.2.5
Django: 1.8
PostgreSQL: 9.4
Python: 2.7.10
os: Windows 7-x64

expected:
a model with a PostgreSQL ArrayField, base_Field models.FloatField with null=True should serialize when any item in the array field is None

observed:
the ListField child to_representation raises an exception

float() argument must be a string or a number

Basically what I think is happening is that the serializer.to_representation normally skips the field.to_representation call if the attributes value is None but it doesn't seem to have any way to handle the ListField children's attributes, which might be None. Maybe this is expected behavior? Or it is updated in DRF-3.3? Unfortunately I had trouble with base python classes, not django models in drf-3.3.

full django traceback

Environment:


Request Method: GET
Request URL: http://localhost:8000/requests/

Django Version: 1.8.5
Python Version: 2.7.10
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'simengapi_app',
 'rest_framework')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware')


Traceback:
File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Python27\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)
File "C:\Python27\lib\site-packages\rest_framework\viewsets.py" in view
  87.             return self.dispatch(request, *args, **kwargs)
File "C:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
  466.             response = self.handle_exception(exc)
File "C:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
  463.             response = handler(request, *args, **kwargs)
File "C:\Python27\lib\site-packages\rest_framework\mixins.py" in list
  45.             return self.get_paginated_response(serializer.data)
File "C:\Python27\lib\site-packages\rest_framework\serializers.py" in data
  663.         ret = super(ListSerializer, self).data
File "C:\Python27\lib\site-packages\rest_framework\serializers.py" in data
  228.                 self._data = self.to_representation(self.instance)
File "C:\Python27\lib\site-packages\rest_framework\serializers.py" in to_representation
  603.             self.child.to_representation(item) for item in iterable
File "C:\Python27\lib\site-packages\rest_framework\serializers.py" in to_representation
  461.                 ret[field.field_name] = field.to_representation(attribute)
File "C:\Python27\lib\site-packages\rest_framework\fields.py" in to_representation
  1450.         return [self.child.to_representation(item) for item in data]
File "C:\Python27\lib\site-packages\rest_framework\fields.py" in to_representation
  873.         return float(value)

Exception Type: TypeError at /requests/
Exception Value: float() argument must be a string or a number

pseudocode of django model field:

efficiencyGCE = ArrayField(verbose_name='GCE Efficiency',
                           base_field=models.FloatField(null=True, blank=True))

and the serializer for it:

class RequestSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Request
@mikofski
Copy link
Author

mikofski commented Dec 1, 2015

[note: edited 2015-12-01]

I fixed this by creating custom list field and adding the if item is not None inside the list comprehension of ListField.to_representation

class CustomListField(serializers.ListField):
    def to_representation(self, data):
        return  [self.child.to_representation(item) if item is not None else None for item in data]

@xordoquy
Copy link
Collaborator

xordoquy commented Dec 1, 2015

I'm not sure how should DRF behave when it receives something like:

[1, 2, None, 3]

@mikofski
Copy link
Author

mikofski commented Dec 1, 2015

I think just like that. Note I edited the fix above to return None if the value is None. I think that validation has already occurred, since this comes from a model, so if null=True is in the model, then a None here is validated. So I don't know if or when checking for allow_null would be useful.

return [self.child.to_representation(item) if item is not None else None for item in data]

@kevin-brown
Copy link
Member

I believe this was fixed in #4118.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants