Django-filter: TypeError : impossible de décaper les objets odict_items en python 3.5

Créé le 14 nov. 2016  ·  7Commentaires  ·  Source: carltongibson/django-filter

Bonjour, j'ai détecté une erreur lors de l'instanciation de la classe dérivée de FilterSet en python>=3.5. En 3.4 tout fonctionne bien.

File "/home/dan/venvs/notes3.5/lib/python3.5/site-packages/django_filters/filterset.py" in __init__
  291.         self.filters = copy.deepcopy(self.base_filters)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in deepcopy
  182.                 y = _reconstruct(x, rv, 1, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in _reconstruct
  320.                 value = deepcopy(value, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in deepcopy
  182.                 y = _reconstruct(x, rv, 1, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in _reconstruct
  297.             state = deepcopy(state, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in deepcopy
  155.         y = copier(x, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in _deepcopy_dict
  243.         y[deepcopy(key, memo)] = deepcopy(value, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in deepcopy
  155.         y = copier(x, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in _deepcopy_dict
  243.         y[deepcopy(key, memo)] = deepcopy(value, memo)

File "/home/dan/venvs/notes3.5/lib/python3.5/copy.py" in deepcopy
  174.                         rv = reductor(4)

Exception Type: TypeError at /notes/
Exception Value: can't pickle odict_items objects

Exemple de ma classe FilterSet. Les champs DateTimeFilter et CommaSeparatedCharFilter sont personnalisés :

class NoteListFilterset(django_filters.FilterSet):
    strict = STRICTNESS.RAISE_VALIDATION_ERROR

    keywords = CommaSeparatedCharFilter(name='keyword', lookup_expr='in')
    datetime_from = DateTimeFilter(name='datetime', lookup_expr='gte')
    datetime_to = DateTimeFilter(name='datetime', lookup_expr='lte')
    get_hidden = django_filters.MethodFilter(method='filter_by_get_hidden')

Commentaire le plus utile

Pour ceux qui rencontrent encore ce problème, je l'ai résolu comme ceci:

list(CATEGORIES.items())

Tous les 7 commentaires

Salut @dangusev. La première réaction est que cela n'a pas de sens. Deux réflexions :

  • La suite de tests est exécutée avec python 3.5, ce genre de problème aurait été détecté.
  • base_filters doit être un OrderedDict , pas un odict_items . Est-ce que quelque chose remplace base_filters ?

Désolé mon mauvais). J'ai beaucoup de code comme celui-ci :

category = ChoiceField(choices=CATEGORIES.items())

Lorsque copy.deepcopy() est appelé sur self.base_fields, il essaie de sélectionner des choix de champs et échoue, car les choix sont de type dict_items.

Pour ceux qui rencontrent encore ce problème, je l'ai résolu comme ceci:

list(CATEGORIES.items())

[Avec Python 3.85 et Django 3.1.1] De même, j'obtiens cette erreur dans l'une de mes vues de liste :

TypeError: cannot pickle 'dict_items' object

Rien dans le backtrace n'est dans mon code:
https://pastebin.com/S4xn8zpT

Il s'avère que le problème était d'ajouter une liste choices à un CharField dans mon modèle :

échoue:

record_request_status = models.CharField(max_length=4, null=True, choices=RECORD_REQUEST_STATUS)

fonctionne bien :

record_request_status = models.CharField(max_length=4, null=True)

RECORD_REQUEST_STATUS est un dict :

with open('case-manager/src/json_fixtures/record_request_status.json') as json_file:
        RECORD_REQUEST_STATUS = json.load(json_file).items()

L'attribution de cette même liste choices à d'autres CharField dans le modèle fonctionne très bien.
L'affectation d'autres listes choices à record_request_status échoue également.

cela marche:

record_request_status = models.CharField(max_length=4, null=True, choices=list(RECORD_REQUEST_STATUS))

Quelqu'un peut-il expliquer ce qui se passe?

@paulschreiber dans votre situation RECORD_REQUEST_STATUS renvoie un dict_items tapez au lieu d'une liste primitive ou Tuple .. dict_items n'est pas un type connu pour cornichon à convertir il jette cette erreur . dict_items a les bonnes méthodes implémentées pour compter comme un itérateur, donc la méthode list fonctionne pour la convertir et donc les choix peuvent enfin accepter ce que vous transmettez.

Espérons que cela l'explique en bonne forme, cela fait quelques années que je n'ai pas regardé cela pour la dernière fois.

@ Ryanb58 Je ne comprends pas pourquoi cela échoue uniquement pour ce champ, mais fonctionne pour tous les autres champs de mes différents modèles. Dans chaque cas, je lis dans un fichier JSON qui est un dictionnaire.

@paulschreiber Je suis intéressé par le problème mais je ne veux pas non plus faire exploser ce fil. On dirait que cela pourrait être quelque chose en dehors de la portée de ce projet spécifique. Je vais vous envoyer un e-mail.

Cette page vous a été utile?
0 / 5 - 0 notes