У меня есть GET
конечную точку, я пытаюсь проверить с помощью APIRequestFactory
, следуя методике, описанной в этом SO сообщение: https://stackoverflow.com/a/28429089MultiValueDictKeyError при тестировании GET конечную точку с помощью APIRequestFactory
Во-первых, я знаю, что это конечная точка работает, потому что я получить ожидаемое поведение при отправке запроса GET
через cURL.
curl -X GET -H "Content-Type: application/json" -i -d "{\"cardinal_key\":12XXXX3, \"cardinal_type\":\"Npis\", \"terminal_type\":\"Deas\", \"candidate_count\":2}" http://127.0.0.1:8000/v1/ranked_results/
HTTP/1.0 200 OK
Date: Mon, 28 Mar 2016 22:29:29 GMT
Server: WSGIServer/0.2 CPython/3.4.3
X-Frame-Options: SAMEORIGIN
Allow: GET, HEAD, OPTIONS
Vary: Accept, Cookie
Content-Type: application/json
{"npi":"12XXXX3","first_name":"XXXXXX","middle_name":null,"last_name":"XXXXXX","full_name":"XXXXX, XXXX XXXXX","link_candidates":{"FXXXXX9":0.9900022451986468,"BXXXXXXX3":0.8483023431385707}}
Однако, когда я попытался сделать эмулировать этот запрос, используя завод, я получил ValueError
исключение (полный след ниже):
from rest_framework.test import APIRequestFactory
from linker.views import RankedResults
factory = APIRequestFactory()
options = {"cardinal_key":12XXXX3, "cardinal_type":"Npis", "terminal_type":"Deas", "candidate_count":2}
request = factory.get('/v1/ranked_results/', json.dumps(options), content_type='application/json')
view = RankedResults.as_view()
response = view(request)
ValueError: need more than 1 value to unpack
Моя следующая мысль была что-то было не работает, потому что я пытался отправить запрос как JSON, поэтому я попробовал сделать запрос без JSON, а затем получил MultiValueDictKeyError
:
from rest_framework.test import APIRequestFactory
from linker.views import RankedResults
factory = APIRequestFactory()
options = {"cardinal_key":12XXXX3, "cardinal_type":"Npis", "terminal_type":"Deas", "candidate_count":2}
request = factory.get('/v1/ranked_results/', options)
view = RankedResults.as_view()
response = view(request)
MultiValueDictKeyError: "'cardinal_type'"
Мое понимание MultiValueDictKeyError
исключением является то, что это происходит, когда ключ отсутствует в словаре. Более того, в документации указано, что MultiValueDict
используется для случая, когда у вас есть несколько значений с одним и тем же ключом. Я не уверен, почему я это вижу, потому что это не так с запросом, который я пытаюсь создать.
Я в затруднении здесь - чего мне не хватает?
вид:
class RankedResults(APIView):
def get(self, request):
cardinal_instance = apps.get_model('warehouse', request.data['cardinal_type']).objects.get(reference_key=request.data['cardinal_key'])
serializer = LinkModelSerializer(cardinal_instance, context=request.data)
return Response(serializer.data)
сериализатору:
class LinkModelSerializer(serializers.ModelSerializer):
link_candidates = serializers.SerializerMethodField('get_candidate_links')
def get_candidate_links(self, obj):
terminal = apps.get_model('warehouse', self.context['terminal_type'])
n = self.context['candidate_count']
return dict(obj.top_n_candidates(terminal, n))
class Meta:
model = warehouse.Npis
fields = ('npi', 'first_name', 'middle_name', 'last_name', 'full_name', 'link_candidates')
read_only_fields = ('link_candidates')
трассировки для случая, когда я пытался отправить запрос JSON:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-20-6b10ed2040c0> in <module>()
2 factory = APIRequestFactory()
3 options = {"cardinal_key":12XXXX3, "cardinal_type":"Npis", "terminal_type":"Deas", "candidate_count":2}
----> 4 request = factory.get('/v1/ranked_results/', json.dumps(options), content_type='application/json')
5 view = RankedResults.as_view()
6 response = view(request)
~/lib/python3.4/site-packages/rest_framework/test.py in get(self, path, data, **extra)
79 def get(self, path, data=None, **extra):
80 r = {
---> 81 'QUERY_STRING': urlencode(data or {}, doseq=True),
82 }
83 # Fix to support old behavior where you have the arguments in the url
~/lib/python3.4/site-packages/django/utils/http.py in urlencode(query, doseq)
94 [(force_str(k),
95 [force_str(i) for i in v] if isinstance(v, (list, tuple)) else force_str(v))
---> 96 for k, v in query],
97 doseq)
98
~/lib/python3.4/site-packages/django/utils/http.py in <listcomp>(.0)
94 [(force_str(k),
95 [force_str(i) for i in v] if isinstance(v, (list, tuple)) else force_str(v))
---> 96 for k, v in query],
97 doseq)
98
ValueError: need more than 1 value to unpack
... Наконец след, когда Я попробовал это без запроса JSON:
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
~/lib/python3.4/site-packages/django/utils/datastructures.py in __getitem__(self, key)
82 try:
---> 83 list_ = super(MultiValueDict, self).__getitem__(key)
84 except KeyError:
KeyError: 'cardinal_type'
During handling of the above exception, another exception occurred:
MultiValueDictKeyError Traceback (most recent call last)
<ipython-input-17-559ee170e692> in <module>()
4 request = factory.get('/v1/ranked_results/', options)
5 view = RankedResults.as_view()
----> 6 response = view(request)
~/lib/python3.4/site-packages/django/views/decorators/csrf.py in wrapped_view(*args, **kwargs)
56 # function.
57 def wrapped_view(*args, **kwargs):
---> 58 return view_func(*args, **kwargs)
59 wrapped_view.csrf_exempt = True
60 return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)
~/lib/python3.4/site-packages/django/views/generic/base.py in view(request, *args, **kwargs)
66 self.args = args
67 self.kwargs = kwargs
---> 68 return self.dispatch(request, *args, **kwargs)
69 view.view_class = cls
70 view.view_initkwargs = initkwargs
~/lib/python3.4/site-packages/rest_framework/views.py in dispatch(self, request, *args, **kwargs)
464
465 except Exception as exc:
--> 466 response = self.handle_exception(exc)
467
468 self.response = self.finalize_response(request, response, *args, **kwargs)
~/lib/python3.4/site-packages/rest_framework/views.py in dispatch(self, request, *args, **kwargs)
461 handler = self.http_method_not_allowed
462
--> 463 response = handler(request, *args, **kwargs)
464
465 except Exception as exc:
~/views.py in get(self, request)
36 class RankedResults(APIView):
37 def get(self, request):
---> 38 cardinal_instance = apps.get_model('warehouse', request.data['cardinal_type']).objects.get(reference_key=request.data['cardinal_key'])
39 serializer = LinkModelSerializer(cardinal_instance, context=request.data)
40 return Response(serializer.data)
~/lib/python3.4/site-packages/django/utils/datastructures.py in __getitem__(self, key)
83 list_ = super(MultiValueDict, self).__getitem__(key)
84 except KeyError:
---> 85 raise MultiValueDictKeyError(repr(key))
86 try:
87 return list_[-1]
MultiValueDictKeyError: "'cardinal_type'"
Можете ли вы поэтому напечатайте 'request.data' методом' get', используя первый подход? – AKS
'------------------------------------------------ --------------------------- ' ' AttributeError Traceback (последний последний вызов) ' ' в () ' ' ----> 1 request.data' 'AttributeError: объект WSGIRequest 'не имеет атрибута' data'' –
Однако я могу видеть строку запроса, когда смотрю' request .__ dict__' (это выдержка): '' QUERY_STRING ':' cardinal_type = Npis & cardinal_key = 1XXXXXX3 & terminal_type = Deas & candid_count = 2 ', ' –