python - Django request data returns str instead of list -


i'm developing rest api django , rest-framework. have endpoint takes post request kind of json:

{         "pipeline": ["bayes"],         "material": [             "rakastan iloisuutta!",             "autojen kanssa pitää olla varovainen.",             "paska kesä taas. kylmää ja sataa"         ]     } 

it machine-learning analysis api , json tells use bayes classifier provided strings , return results. works fine when test manually doing post requests. however, breaks down when try write unit test. have following test:

class classifytextapitests(apitestcase):     fixtures = ['fixtures/analyzerfixtures.json'] #suboptimal fixture since requires bayes.pkl in /assets/classifiers folder      def test_classification(self):         """ make sure api respond correctly when required url params supplied.         """         response = self.client.post(reverse('analyzer_api:classifytext'), {             "pipeline": ["bayes"],             "material": [                 "rakastan iloisuutta!",                 "autojen kanssa pitää olla varovainen.",                 "paska kesä taas. kylmää ja sataa",             ]         })         self.asserttrue(status.is_success(response.status_code))         self.assertequal(response.data[0], 1) 

test fails everytime because of latter assert gives "assertionerror: 'p' != 1"

here view code:

class classifytext(apiview):     """     takes text snippet parameter , returns analyzed result.     """     authentication_classes = (authentication.tokenauthentication,)     permission_classes = (permissions.allowany,)     parser_classes = (jsonparser,)      def post(self, request, format=none):         try:             self._validate_post_data(request.data)             print("juttu", request.data["material"])             #create pipeline request             pipeline = pipeline()             component_name in request.data["pipeline"]:                 pipeline.add_component(component_name)              response = pipeline.execute_pipeline(request.data['material'])             status_code = status.http_200_ok          except exception e:             response = {"message": "please provide proper data.",                         "error": str(e) }             status_code = status.http_400_bad_request          return response(response, status=status_code)      def _validate_post_data(self, data):         if "pipeline" not in data:             raise invalidrequest("pipeline field missing. should array of components used in analysis. available components @ /api/classifiers")          if len(data["pipeline"]) < 1:             raise invalidrequest("pipeline array empty.")          if "material" not in data:             raise invalidrequest("material analyzed missing. please provide array of strings.")          if len(data["material"]) < 1:             raise invalidrequest("material analyzed missing, array empty. please provide array of strings.") 

the interesting part when fired debugger check happens here. turns out line

request.data['material'] 

gives last entry of list in in request, in case

"paska kesä taas. kylmää ja sataa"

however, while inspect contents of request.data, shows querydict lists pipeline , material in request. why string instead of material list when call request.data["material"] ? there have forgotten , have specify kind of serializer? , why works during normal execution not tests?

i'm using django 1.8 python 3. also, i'm not tying view specific model.

finally here debugger shows when put break points view: request.data:

querydict: {'material': ['rakastan iloisuutta!', 'autojen kanssa pitää olla varovainen.', 'paska kesä taas. kylmää ja sataa'], 'pipeline': ['bayes']} 

asd = request.data["material"]:

'paska kesä taas. kylmää ja sataa' 

this because querydict returns last value of list in __getitem__:

querydict.getitem(key)

returns value given key. if key has more 1 value, getitem() returns last value. raises django.utils.datastructures.multivaluedictkeyerror if key not exist. (this subclass of python’s standard keyerror, can stick catching keyerror.)

https://docs.djangoproject.com/en/1.8/ref/request-response/#django.http.querydict.getitem

if post form, in key maps list:

d = {"a": 123, "b": [1,2,3]} requests.post("http://127.0.0.1:6666", data=d) 

this in request body:

a=123&b=1&b=2&b=3 

since test method post data form, request.data querydict (the same request.post), hence last value in list when getting request.data.

to expected behavior, post data json in request body (as in @vladir parrado cruz's answer).


Comments

Popular posts from this blog

javascript - Using jquery append to add option values into a select element not working -

Android soft keyboard reverts to default keyboard on orientation change -

jquery - javascript onscroll fade same class but with different div -