This question has been SOLVED by myself after better looking at it. Please read my answer below.
I am getting a "The fields
option must be a list or tuple. Got str." when running my Django app.
Running exactly the same code with the debugger, and if I have a breakpoint in the line of the error, then it won't fail and what should be a tuple seems to be a tuple.
The problem seems to be located in the following code inside a DRF ModelSerializer:
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
# Instantiate the superclass normally
super(ChHiveLevel1Serializer, self).__init__(*args, **kwargs)
if fields is not None:
# Drop fields that are specified in the `fields` argument.
for field_name in fields:
self.fields.pop(field_name)
print("fields to be included: ", self.fields)
In the views.py I just do: ...
hives = profile.hive_subscriptions
# En fields se le pasa el campo a eliminar del serializador
fields = ('priority', )
serializer = serializers.ChHiveLevel1Serializer(hives, fields=fields, many=True)
...
And this is the traceback:
Internal Server Error: /profiles/diegoocampo8/hives/
Traceback (most recent call last):
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/django/core/handlers/base.py", line 111, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/django/views/decorators/csrf.py", line 57, in wrapped_view
return view_func(*args, **kwargs)
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/django/views/generic/base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/views.py", line 452, in dispatch
response = self.handle_exception(exc)
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/views.py", line 449, in dispatch
response = handler(request, *args, **kwargs)
File "/home/diego/PycharmProjects/chattyhive/API/views.py", line 271, in get
serializer = serializers.ChHiveLevel1Serializer(hives, fields=fields, many=True)
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/serializers.py", line 96, in __new__
return cls.many_init(*args, **kwargs)
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/serializers.py", line 116, in many_init
child_serializer = cls(*args, **kwargs)
File "/home/diego/PycharmProjects/chattyhive/API/serializers.py", line 274, in __init__
print("fields to be included: ", self.fields)
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/utils/serializer_helpers.py", line 120, in __repr__
return dict.__repr__(self.fields)
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/serializers.py", line 611, in __repr__
return unicode_to_repr(representation.list_repr(self, indent=1))
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/utils/representation.py", line 97, in list_repr
if hasattr(child, 'fields'):
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/serializers.py", line 313, in fields
for key, value in self.get_fields().items():
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/serializers.py", line 837, in get_fields
field_names = self.get_field_names(declared_fields, info)
File "/home/diego/virtualenvs/chattyhive3.3.4/lib/python3.3/site-packages/rest_framework/serializers.py", line 889, in get_field_names
type(fields).__name__
TypeError: The `fields` option must be a list or tuple. Got str.
[05/May/2015 17:30:34] "GET /profiles/diegoocampo8/hives/ HTTP/1.1" 500 136024
If I remove the print("fields to be included: ", self.fields)
then I got the same error but it will point to the line serializer = serializers.ChHiveLevel1Serializer(hives, fields=fields, many=True)
in the views.py
Ok, I am still a noob in Python and I could be doing something very wrong, but what I can't understand is why if I insert a breakpoint in the print I've just mentioned, and I do the same api request with the debug on, then the code just works: I get my response just as I wanted, and it doesn't give any error (if I remove the breakpoint it will again give the error even if launching with the debugger).
Do you guys have any idea of what could be wrong? Thanks a lot in advance. Ask me for any extra info if you need it!
EDIT: Further explanations:
The whole serializer is this:
class ChHiveLevel1Serializer(serializers.ModelSerializer):
"""Used by the following API methods: GET hive list,
"""
category = serializers.SlugRelatedField(read_only=True, slug_field='code')
languages = serializers.SlugRelatedField(source='_languages', many=True, read_only=True, slug_field='language')
# If in the POST we only need to establish the relationship with User model (not update the model itself) we
# set read_only to True
creator = serializers.SlugRelatedField(read_only=True, slug_field='public_name')
tags = serializers.SlugRelatedField(many=True, read_only=True, slug_field='tag')
public_chat = ChPublicChatLevel1Serializer(many=False, read_only=True)
community_public_chats = ChCommunityPublicChatLevel1Serializer(many=True, read_only=True)
subscribed_users_count = serializers.IntegerField(source='get_subscribed_users_count', read_only=True)
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
# Instantiate the superclass normally
super(ChHiveLevel1Serializer, self).__init__(*args, **kwargs)
if fields is not None:
# Drop fields that are specified in the `fields` argument.
for field_name in fields:
self.fields.pop(field_name)
print("fields to be included: ", self.fields)
class Meta:
model = ChHive
fields = ('name', 'slug', 'description', 'category', 'languages', 'creator', 'creation_date', 'tags',
'priority', 'type', 'public_chat', 'community_public_chats', 'subscribed_users_count')
I know its confusing to have 3 different 'fields' so I clarify this:
in the views I am passing a param 'fields' to the serializer, this is a tuple that contain names of fields to be dynamically removed from the serializer. Then inside the init I take pop out this param (so it is not sent to the superclass) and assign it the local tuple 'fields'. Finally, inside the 'if fields is not None' I am removing from self.fields (these are the fields defined in the serializer) the fields with name matching those inside the local tuple. I hope I could explain it better now.
Here is a video showing how when debugging and stopping at the breakpoint it just works: http://youtu.be/RImEMebBGLY
SOLUTION: First of all it seems to me that there is a bug with either pydevd or Django Rest Framework, that made my code work when in debugging mode and stoping in breakpoints (showed in the video). But I am not expert in Django / Python so it could be the expected behaviour.
As seen in the code above, the ChHiveLevel1Serializer serializer has nested serializers, being one of them, for example, ChPublicChatLevel1Serializer. Lets see how this serializer looks like:
class ChCommunityPublicChatListLevel1Serializer(serializers.ModelSerializer):
"""Used by the following API methods: GET hive list,
"""
chat = serializers.SlugRelatedField(read_only=True, slug_field='chat_id', allow_null=True)
class Meta:
model = ChCommunityPublicChat
fields = ('chat')
As the error said, fields is defined as a string instead of a tuple. The correct form would be:
class ChCommunityPublicChatListLevel1Serializer(serializers.ModelSerializer):
"""Used by the following API methods: GET hive list,
"""
chat = serializers.SlugRelatedField(read_only=True, slug_field='chat_id', allow_null=True)
class Meta:
model = ChCommunityPublicChat
fields = ('chat', )
While I agree that I made a mistake in how i defined this tuple, I still can't understand why with the debugger set to ON, it would just work. (like if using the debugger and stopping in breakpoints it suddenly interprets ('chat') as a tuple instead of a string).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With