master
๋ถ๊ธฐ์ ํด๋น ๋ฌธ์ ๊ฐ ์์์ ํ์ธํ์ต๋๋ค.์ํธ
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
์ด๊ฒ์ /api/v1/incidents/์ TypeError๋ฅผ ์ ๊ณตํฉ๋๋ค.
ํด์ํ ์ ์๋ ์ ํ: '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'}
๋๋จธ์ง ํ๋ ์์ํฌ์ ํ์ ๊ฐ๋ฅํ API ๋ณด๊ธฐ ํ์ด์ง๋ฅผ ํ์ํด์ผ ํฉ๋๋ค.
/api/v1/incidents/์์ TypeError ์คํจ
ํด์ํ ์ ์๋ ์ ํ: 'dict'
์๋
ํ์ธ์ @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
๋ฌธ์ ๋ to_representation
๋ฉ์๋์์ unhashable type: 'collections.OrderedDict'
๋ฅผ ์ป๊ณ ์๋ค๋ ๊ฒ์
๋๋ค. ์ ๊ทธ๋ฐ์ง ์ดํด๊ฐ ๋์ง ์์ต๋๋ค.
์ผ๋ถ ์
๊ทธ๋ ์ด๋ ์ ์?
dict
์ ํ์ to_representation()์ ๋ํ ๋ฐํ์ ๊ตฌํํ๊ธฐ ๋๋ฌธ์ ์ด ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๊ทธ๋์ ํ์ด์ง์์ ์์์ ์์ฑํ๋ ค๊ณ ํ ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.
์๋ง๋ ๊ทธ๊ฒ์ ๋ถ๋ช
ํ๊ณ ์ด๋ฆฌ์์ ์ผ์ด์ง๋ง ๊ธฐ์กด ํด๋์ค๋ก ์๋๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
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
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๊ฐ๋ฅํ ํ ์ง๋ ฌ ๋ณํ๊ธฐ์
create
๋ฐupdate
๋ฉ์๋๋ฅผ ๋ฎ์ด์ฐ์ง ์์ผ๋ ค๊ณ ํฉ๋๋ค. ์ด๋ฅผ ์ํด ๋๋ ์ด๊ฒ์ ํ๋ ๋ฐ ๋์์ด ๋๋ ์์ ํด๋์ค๋ฅผ ์์ฑํ์ง๋ง ์ด๋ค ์ด์ ๋ก ์ด ํด๋์ค์ ๊ด๋ จ๋ ์ค๋ฅ๊ฐ ์์ต๋๋ค.๋ฌธ์ ๋
to_representation
๋ฉ์๋์์unhashable type: 'collections.OrderedDict'
๋ฅผ ์ป๊ณ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ ๊ทธ๋ฐ์ง ์ดํด๊ฐ ๋์ง ์์ต๋๋ค.