Django-rest-framework: TypeError unhashable type: 'dict' с RelatedField Π² сСриализаторах

Π‘ΠΎΠ·Π΄Π°Π½Π½Ρ‹ΠΉ Π½Π° 28 Π°ΠΏΡ€. 2017  Β·  3ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ  Β·  Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: encode/django-rest-framework

ΠšΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΡŒΠ½Ρ‹ΠΉ список

  • [x] Π― ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€Π΄ΠΈΠ», Ρ‡Ρ‚ΠΎ эта ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° сущСствуСт Π² Π²Π΅Ρ‚Π²ΠΈ master ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΡ‹ Django REST.
  • [x] Π― искал ΠΏΠΎΡ…ΠΎΠΆΠΈΠ΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ ΠΊΠ°ΠΊ Π² ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹Ρ…, Ρ‚Π°ΠΊ ΠΈ Π² Π·Π°ΠΊΡ€Ρ‹Ρ‚Ρ‹Ρ… Ρ‚ΠΈΠΊΠ΅Ρ‚Π°Ρ…, ΠΈ Π½Π΅ ΠΌΠΎΠ³Ρƒ Π½Π°ΠΉΡ‚ΠΈ Π΄ΡƒΠ±Π»ΠΈΠΊΠ°Ρ‚ΠΎΠ².
  • [x] Π­Ρ‚ΠΎ Π½Π΅ вопрос использования. (ВмСсто этого ΠΈΡ… слСдуСт Π½Π°ΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ Π² Π΄ΠΈΡΠΊΡƒΡΡΠΈΠΎΠ½Π½ΡƒΡŽ Π³Ρ€ΡƒΠΏΠΏΡƒ .)
  • [x] Π­Ρ‚ΠΎ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒΡΡ ΠΊΠ°ΠΊ сторонняя Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°. (ΠœΡ‹ ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡ΠΈΡ‚Π°Π΅ΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½ΠΎΠ²Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π±Ρ‹Π»ΠΈ Π² Ρ„ΠΎΡ€ΠΌΠ΅ сторонних Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ, Π³Π΄Π΅ это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ.)
  • [x] Π― свСл ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ ΠΊ ΠΏΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠ΅ΠΌΡƒ ΡΠ»ΡƒΡ‡Π°ΡŽ.
  • [] Π― Π²ΠΊΠ»ΡŽΡ‡ΠΈΠ» Π½Π΅ΡƒΠ΄Π°Ρ‡Π½Ρ‹ΠΉ тСст Π² качСствС запроса Π½Π° вытягиваниС. (Если Π²Ρ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ этого ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ, ΠΌΡ‹ всС Ρ€Π°Π²Π½ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΡ€ΠΈΠ½ΡΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ.)

Код

from rest_framework import serializers
from incidents.models import Incident

class NodeDataField(serializers.RelatedField):

    def to_representation(self, node):
        return {
            "id": node.id,
            "name": node.name,
            "ipaddress": node.ipv4
        }

    def to_internal_value(self, id):
        pass

Π­Ρ‚ΠΎ Π΄Π°Π΅Ρ‚ TypeError Π² / api / v1 / incidents /
Π½Π΅Ρ…ΡΡˆΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ Ρ‚ΠΈΠΏ: 'dict'

unhashable type: 'dict'
5       <label class="col-sm-2 control-label {% if style.hide_label %}sr-only{% endif %}">
6         {{ field.label }}
7       </label>
8     {% endif %}
9   
10    <div class="col-sm-10">
11      <select class="form-control" name="{{ field.name }}">
12        {% if field.allow_null or field.allow_blank %}
13          <option value="" {% if not field.value %}selected{% endif %}>--------</option>
14        {% endif %}
15  

      {% for select in field.iter_options %}



16            {% if select.start_option_group %}
17              <optgroup label="{{ select.label }}">
18            {% elif select.end_option_group %}
19              </optgroup>
20            {% else %}
21              <option value="{{ select.value }}" {% if select.value|as_string == field.value|as_string %}selected{% endif %} {% if select.disabled %}disabled{% endif %}>{{ select.display_text }}</option>
22            {% endif %}
23       {% endfor %}
24     </select>

Врассировки стСка

/opt/grofers/firealarm-api/api/firealarm_api/lib/python3.4/_collections_abc.py in update
                                    self[key] = value
     ...
β–Ά Local vars
/opt/grofers/firealarm-api/api/firealarm_api/lib/python3.4/collections/__init__.py in __setitem__
            self.__update(*args, **kwds)
        def __setitem__(self, key, value,
                        dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):
            'od.__setitem__(i, y) <==> od[i]=y'
            # Setting a new item creates a new link at the end of the linked list,
            # and the inherited dictionary is updated with the new key/value pair.
                        if key not in self:
     ...
                self.__map[key] = link = Link()
                root = self.__root
                last = root.prev
                link.prev, link.next, link.key = last, root, key
                last.next = link
                root.prev = proxy(link)
β–Ό Local vars
Variable    Value
self    
OrderedDict()
dict_setitem    
<slot wrapper '__setitem__' of 'dict' objects>
value   
'Node object'
proxy   
<built-in function proxy>
Link    
<class 'collections._Link'>
key     
{'id': 1, 'ipaddress': '172.31.84.130', 'name': 'abc123.con'}

ДСйствия ΠΏΠΎ Π²ΠΎΡΠΏΡ€ΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΡŽ

  1. Π’Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚Π΅ Π²Ρ‹Π·ΠΎΠ² GET для прСдставлСния, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ это ΠΏΠΎΠ»Π΅ связанного сСриализатора, ΠΈ /? Format = api Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ с ошибкой, описанной Π²Ρ‹ΡˆΠ΅, Ρ‚ΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ /? Format = json Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚, ΠΊΠ°ΠΊ ΠΈ оТидалось, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΎΡ‚Π²Π΅Ρ‚.

    ОТидаСмоС повСдСниС

Он Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ ΠΏΡ€ΠΎΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Π΅ΠΌΡƒΡŽ страницу просмотра API rest-framework

ЀактичСскоС ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅

Ошибка с TypeError в / api / v1 / incidents /
Π½Π΅Ρ…Π΅ΡˆΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ Ρ‚ΠΈΠΏ: 'dict'

Π‘Π°ΠΌΡ‹ΠΉ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹ΠΉ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ

Π― ΠΏΡ‹Ρ‚Π°ΡŽΡΡŒ ΠΊΠ°ΠΊ-Ρ‚ΠΎ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ пСрСзаписи ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² сСриализатора create ΠΈ update Ρ‚Π°ΠΌ, Π³Π΄Π΅ это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ. Для этого я написал нСбольшой класс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ ΠΌΠ½Π΅ Π² этом, Π½ΠΎ ΠΏΠΎ ΠΊΠ°ΠΊΠΎΠΉ-Ρ‚ΠΎ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π΅ Ρƒ мСня Π΅ΡΡ‚ΡŒ ошибка, связанная с этим.

class PrimaryKeyField(serializers.RelatedField):
    def __init__(self, serializer, **kwargs):
        self.serializer = serializer(**kwargs)
        if "queryset" not in kwargs:
            kwargs["queryset"] = self.serializer.Meta.model.objects.all()
        self.pk_field = serializers.PrimaryKeyRelatedField(**kwargs)

        super().__init__(**kwargs)

    def to_representation(self, instance):
        return self.serializer.to_representation(instance)

    def to_internal_value(self, data):
        try:
            return self.pk_field.to_internal_value(data["id"])
        except TypeError:
            return data

Π”Π΅Π»ΠΎ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ я ΠΏΠΎΠ»ΡƒΡ‡Π°ΡŽ unhashable type: 'collections.OrderedDict' Π² ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ to_representation . И я Π½Π΅ понимаю ΠΏΠΎΡ‡Π΅ΠΌΡƒ.

ВсС 3 ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ

ΠŸΡ€ΠΈΠ²Π΅Ρ‚, @manjitkumar - RelatedField ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ связанный ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΊΠ°ΠΊ ΠΎΠ΄Π½ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, слаг, ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹ΠΉ ΠΊΠ»ΡŽΡ‡, URL-адрСс ΠΈ Ρ‚. Π”.). Если Π²Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ прСдставлСниС Π²Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, Π²Π°ΠΌ слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΉ сСриализатор .

Π― ΠΏΡ‹Ρ‚Π°ΡŽΡΡŒ ΠΊΠ°ΠΊ-Ρ‚ΠΎ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ пСрСзаписи ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² сСриализатора create ΠΈ update Ρ‚Π°ΠΌ, Π³Π΄Π΅ это Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ. Для этого я написал нСбольшой класс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ ΠΌΠ½Π΅ Π² этом, Π½ΠΎ ΠΏΠΎ ΠΊΠ°ΠΊΠΎΠΉ-Ρ‚ΠΎ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π΅ Ρƒ мСня Π΅ΡΡ‚ΡŒ ошибка, связанная с этим.

class PrimaryKeyField(serializers.RelatedField):
    def __init__(self, serializer, **kwargs):
        self.serializer = serializer(**kwargs)
        if "queryset" not in kwargs:
            kwargs["queryset"] = self.serializer.Meta.model.objects.all()
        self.pk_field = serializers.PrimaryKeyRelatedField(**kwargs)

        super().__init__(**kwargs)

    def to_representation(self, instance):
        return self.serializer.to_representation(instance)

    def to_internal_value(self, data):
        try:
            return self.pk_field.to_internal_value(data["id"])
        except TypeError:
            return data

Π”Π΅Π»ΠΎ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ я ΠΏΠΎΠ»ΡƒΡ‡Π°ΡŽ unhashable type: 'collections.OrderedDict' Π² ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ to_representation . И я Π½Π΅ понимаю ΠΏΠΎΡ‡Π΅ΠΌΡƒ.

ΠŸΡ€Π΅Π΄Π»ΠΎΠΆΠΈΡ‚ΡŒ ΠΊΠ°ΠΊΠΈΠ΅-Π½ΠΈΠ±ΡƒΠ΄ΡŒ обновлСния?
Π― столкнулся с этой ошибкой, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Ρ‹Π²Π°Π» Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ to_presentation (), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΠΌΠ΅Π» Ρ‚ΠΈΠΏ dict поэтому, ΠΊΠΎΠ³Π΄Π° ΠΎΠ½ пытался ΡΠ³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΠΎΡ€ΠΌΡƒ Π½Π° страницС, ΠΎΠ½ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ» ΠΎΡˆΠΈΠ±ΠΊΡƒ.
Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, это ясно, ΠΈ я Π³Π»ΡƒΠΏ, Π½ΠΎ Π΅ΡΡ‚ΡŒ Π»ΠΈ способ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π½ΠΈΠΆΠ΅ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠ΅ с ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌΠΈ классами?

class AnyRelatedField(serializers.RelatedField):
    def __init__(self, query_fields=tuple(), **kwargs):
        if not query_fields:
            raise NotImplementedError("AnyRelatedField requires a query field names to be provided as a tuple")

        self.query_fields = query_fields
        self.query_objects = Q()

        super().__init__(**kwargs)

    def to_internal_value(self, data):
        for field in self.query_fields:
            if field in ['pk', 'id'] and not isinstance(data, int):
                continue
            self.query_objects |= Q(**{field: data})
        try:
            self.instance = self.queryset.get(self.query_objects)
            return self.instance
        except self.queryset.model.DoesNotExist:
            raise serializers.ValidationError(
                detail="{} object does not exist with {}: {}".format(
                    self.queryset.model.__name__, ', '.join(self.query_fields), data
                ),
                code=self.field_name
            )

    def to_representation(self, val):
        return val
Π‘Ρ‹Π»Π° Π»ΠΈ эта страница ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠΉ?
0 / 5 - 0 Ρ€Π΅ΠΉΡ‚ΠΈΠ½Π³ΠΈ