使用 django 测试客户端发送 JSON
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8583290/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sending JSON using the django test client
提问by Hartley Brody
I'm working on a django a project that will serve as the endpoint for a webhook. The webhook will POST some JSON data to my endpoint, which will then parse that data. I'm trying to write unit tests for it, but I'm not sure if I'm sending the JSON properly.
我正在开发一个 django 项目,该项目将作为 webhook 的端点。webhook 会将一些 JSON 数据发布到我的端点,然后该端点将解析该数据。我正在尝试为它编写单元测试,但我不确定我是否正确发送了 JSON。
I keep getting "TypeError: string indices must be integers" in pipeline_endpoint
我在管道端点中不断收到“类型错误:字符串索引必须是整数”
Here's the code:
这是代码:
# tests.py
from django.test import TestCase
from django.test.client import Client
import simplejson
class TestPipeline(TestCase):
def setUp(self):
"""initialize the Django test client"""
self.c = Client()
def test_200(self):
json_string = u'{"1": {"guid": "8a40135230f21bdb0130f21c255c0007", "portalId": 999, "email": "fake@email"}}'
json_data = simplejson.loads(json_string)
self.response = self.c.post('/pipeline-endpoint', json_data, content_type="application/json")
self.assertEqual(self.response.status_code, "200")
and
和
# views.py
from pipeline.prospect import Prospect
import simplejson
def pipeline_endpoint(request):
#get the data from the json object that came in
prospects_json = simplejson.loads(request.raw_post_data)
for p in prospects_json:
prospect = {
'email' : p['email'],
'hs_id' : p['guid'],
'portal' : p['portalId'],
}
Edit: whole traceback.
编辑:整个追溯。
======================================================================
ERROR: test_200 (pipeline.tests.TestPipeline)
----------------------------------------------------------------------
Traceback (most recent call last):
File "F:\......\pipeline\tests.py", line 31, in test_200
self.response = self.c.post('/pipeline-endpoint', json_string, content_type="application/json")
File "C:\Python27\lib\site-packages\django\test\client.py", line 455, in post
response = super(Client, self).post(path, data=data, content_type=content_type, **extra)
File "C:\Python27\lib\site-packages\django\test\client.py", line 256, in post
return self.request(**r)
File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 111, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "F:\......\pipeline\views.py", line 18, in pipeline_endpoint
'email' : p['email'],
TypeError: string indices must be integers
----------------------------------------------------------------------
Ran 1 test in 0.095s
FAILED (errors=1)
Destroying test database for alias 'default'...
回答by Guillaume Vincent
@mrmagooey is right
@mrmagooey 是对的
def test_your_test(self):
python_dict = {
"1": {
"guid": "8a40135230f21bdb0130f21c255c0007",
"portalId": 999,
"email": "fake@email"
}
}
response = self.client.post('/pipeline-endpoint/',
json.dumps(python_dict),
content_type="application/json")
use json.dumpsinstead of json.loads
使用json.dumps代替json.loads
回答by Chris Lamb
Try:
尝试:
self.client.generic('POST', '/url', json.dumps({'json': 'object'})
回答by amertkara
You can always use the HttpRequest.bodywhich loads the raw request data. This way you can handle your own data processing.
您始终可以使用HttpRequest.body加载原始请求数据。通过这种方式,您可以处理自己的数据处理。
c = Client()
json_str= json.dumps({"data": {"id": 1}})
c.post('/ajax/handler/', data= json_str, content_type='application/json',
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
def index(request):
....
print json.loads(request.body)
回答by Du?an Ma?ar
rest_framework's APIClient(which is the the default client_classin APITestCase) takes care of dumping dictto JSONand it sets proper content type by passing format='json'.
rest_framework的APIClient(这是默认client_class中APITestCase)开倾倒照顾dict到JSON,它通过使设置适当的内容类型format='json'。
from rest_framework import status
from rest_framework.test import APIClient, APITestCase
class MyTestCase(APITestCase):
url = '/url'
def post(self, payload, url=None):
"""
Helper to send an HTTP post.
@param (dict) payload: request body
@returns: response
"""
if url is None:
url = self.url
return self.client.post(url, payload, format='json')
def test_my_function(self):
payload = {
'key': 'value'
}
response = self.post(payload)
self.assertEqual(response.status_code, status.HTTP_200_OK)
回答by czarchaic
You can user iteritemson dictionaries to loop
您可以使用iteritems字典来循环
for index, p in prospects_json.iteritems():
prospect={
'email': p['email'],
}
or alternatively
或者
for index in prospect_json:
prospect={
'email': prospect_json[ index ]['email']
}
回答by Amit Chaudhary
Adding to Guillaume Vincent's answer, from Django 2.1 we no longer need to use json.dumps for passing the data.
除了 Guillaume Vincent 的回答之外,从 Django 2.1 开始,我们不再需要使用 json.dumps 来传递数据。
Changed in Django 2.1: The JSON serialization described above was added. In older versions, you can call json.dumps() on data before passing it to post() to achieve the same thing.
Django 2.1 中的更改:添加了上述 JSON 序列化。在旧版本中,您可以在将数据传递给 post() 之前对数据调用 json.dumps() 以实现相同的目的。

