2015-05-05 13 views
12

Questa domanda è stata SOLVED da solo dopo averlo guardato meglio. Si prega di leggere la mia risposta qui sotto.Python/Django Rest Framework strano errore accadendo solo quando si utilizza debugger


sto ottenendo un "L'opzione fields deve essere una lista o tupla. Got str." quando si esegue la mia app Django. Eseguendo esattamente lo stesso codice con il debugger, e se ho un breakpoint nella riga dell'errore, allora non fallirà e quale dovrebbe essere una tupla sembra essere una tupla.

Il problema sembra essere situato nel seguente codice all'interno di un 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) 

Nel views.py Io faccio solo: ...

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) 
    ... 

e questo è il 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 

Se rimuovo il print("fields to be included: ", self.fields) poi ho avuto la stesso errore ma punterà alla riga serializer = serializers.ChHiveLevel1Serializer(hives, fields=fields, many=True) nel views.py

Ok, sono ancora un noob in Python e potrei fare qualcosa di molto sbagliato, ma quello che non riesco a capire è perché se inserisco un breakpoint nella stampa che ho appena menzionato, e faccio la stessa richiesta API con il debug, quindi il codice funziona: ottengo la mia risposta proprio come volevo, e non dà alcun errore (se rimuovo il punto di interruzione restituirà ancora l'errore anche se si avvia con il debugger).

Avete qualche idea di cosa potrebbe essere sbagliato? Grazie mille in anticipo. Chiedimi eventuali informazioni extra se ne hai bisogno!

EDIT: Ulteriori spiegazioni:

L'intero serializzatore è questo:

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') 

So che la sua fonte di confusione per avere 3 diversi 'campi' in modo da chiarire questo:

nelle viste I sto passando un param 'campi' al serializzatore, questa è una tupla che contiene nomi di campi da rimuovere dinamicamente dal serializzatore. Quindi all'interno del init prendo il pop out di questo parametro (quindi non viene inviato alla superclasse) e gli assegno i 'campi' tupla locali. Infine, dentro 'if fields is not None' sto rimuovendo da self.fields (questi sono i campi definiti nel serializzatore) i campi con nome corrispondenti a quelli all'interno della tupla locale. Spero di poterlo spiegare meglio ora.

Ecco un video che mostra come durante il debug e l'arresto al punto di interruzione funziona da solo: http://youtu.be/RImEMebBGLY

+1

Questo errore si è verificato perché c'era qualcosa di sbagliato quando DRF ha cercato di ottenere una rappresentazione in formato stringa dei campi del serializzatore da stampare. Potresti per favore incollare l'intero serializzatore? In modo che potessi provare a capire cosa c'è che non va. –

+1

Il codice è difficile da seguire. Sembrano esserci 3 diversi nomi di "campi": self.fields, una variabile locale chiamata "fields" in __init __() e ChHiveLevel1Serializer.Meta.fields. L'eccezione TypeError stava controllando ChHiveLevel1Serializer.Meta.fields. Se si pensa e si spiega il motivo dell'utilizzo di tutti e tre, si potrebbe ottenere una correzione. WRT il comportamento quando si imposta un punto di interruzione non si indica se l'esecuzione si è effettivamente interrotta al punto di interruzione e se si è continuato dal punto di interruzione. Potrebbe essere che un thread/richiesta si sia fermato al breakpoint e che il successivo abbia avuto successo. – nmgeek

+0

Ho aggiunto qualche altra informazione. Informazioni sui punti di interruzione: sì, l'esecuzione si è arrestata al punto di interruzione e quindi ho continuato l'esecuzione e ottenuto la risposta prevista dall'API REST che sto costruendo. Ho aggiunto anche un collegamento video che mostra il problema: http://youtu.be/RImEMebBGLY – diegopau

risposta

3

SOLUZIONE: Prima di tutto mi sembra che ci sia un bug sia con pydevd o Django Resto Framework, che ha fatto il mio codice funziona quando si trova in modalità di debug e si ferma nei punti di interruzione (mostrato nel video). Ma non sono esperto in Django/Python, quindi potrebbe essere il comportamento previsto.

Come visto nel codice sopra, il serializzatore ChHiveLevel1Serializer ha serializzatori nidificati, essendo uno di essi, ad esempio, ChPublicChatLevel1Serializer.Vediamo come questo si presenta come serializzatore:

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') 

Come ha detto l'errore, i campi è definito come una stringa invece di una tupla. La forma corretta sarebbe:

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',) 

Mentre sono d'accordo che ho fatto un errore nel modo in cui ho definito questa tupla, non riesco ancora a capire perché con il debugger impostato su ON, sarebbe solo lavorare. (come se si usasse il debugger e si fermasse nei punti di interruzione, improvvisamente interpreta ('chat') come una tupla invece che una stringa).

Problemi correlati