Python 单元测试Django JSON视图

Python 单元测试Django JSON视图,python,json,ajax,django,unit-testing,Python,Json,Ajax,Django,Unit Testing,我正试图为一些Django json_视图编写一些单元测试,但在将json_字符串传递到视图时遇到了问题。我昨天发布了一个关于从JS向Django视图传递json字符串的相关问题,问题是在我的JS中,我只是传递json字符串,需要将字符串作为对象的属性传递,因为我没有做到这一点,所以字符串被作为结果查询dict的键。我再次遇到类似的问题,除了这次是从Django单元测试到Django视图。下面是我的代码的简化版本,它产生了相同的结果 class MyTestCase(TestCase):

我正试图为一些Django json_视图编写一些单元测试,但在将json_字符串传递到视图时遇到了问题。我昨天发布了一个关于从JS向Django视图传递json字符串的相关问题,问题是在我的JS中,我只是传递json字符串,需要将字符串作为对象的属性传递,因为我没有做到这一点,所以字符串被作为结果查询dict的键。我再次遇到类似的问题,除了这次是从Django单元测试到Django视图。下面是我的代码的简化版本,它产生了相同的结果

class MyTestCase(TestCase):
    def setUp(self):
        self.u = User.objects.create_user('test','test','test')
        self.u.is_active = True
        self.u.save()
        self.client.login(username='test',password='test')

    def test_create_object_from_form(self):
        """Test the creation of the Instance from the form data."""
        import json
        json_string json.dumps({'resource':{'type':'book','author':'John Doe'}})
        print(json_string)
        response = self.client.post(reverse('ajax_view'),
                                    {'form':json_string},'json')
        self.assetNotContains(response,'error')
视图是这样的

@json_view
def ajax_view(request):
    """Process the incoming form data."""
    if request.method == 'POST':
        print(request.POST)
        form_data = json.loads(request.POST['form'])
        resource_data = form_data['resource']
        form = MyUserForm(resource_data)

        if form.is_valid():
        ...
下面是运行测试时两个print语句生成的内容。json_字符串是

{"resource": {"type": "book", "author": "John Doe"}}
查询dict看起来像

<QueryDict: {u'{\'form\': \'{"resource": {"type": "book", "author": "John Doe"}}\'}': [u'']}>

我对JS和ajax完全是新手,所以不要担心会伤害我的自尊心,答案可能太接近了,它可能会跳起来咬我。

最终编辑

我最初声明,post调用中需要使用带有@XMLHttpRequest'的header
HTTP\ux\u REQUESTED\u,但在测试中这是错误的。此标头对于csrf中间件是必需的,但在测试中禁用了csrf。然而,我仍然相信,即使中间件禁用了csrf,进行测试也是一种很好的做法,因为大多数javascript库在执行ajax时已经默认通过了这个头部。另外,如果另一段未被禁用的代码曾经使用is_ajax方法,那么您不需要在数小时内调试unittest来找出缺少的头

问题在于内容类型,因为当django在其中获得一个不同于
text/html
的值时,它不会使用默认的post数据处理,即像查询中那样格式化数据:
type=book&author=JohnDoe

那么固定代码是:

response = self.client.post(reverse('ajax_view'),
                            {'form':json_string}, 
                            HTTP_X_REQUESTED_WITH='XMLHttpRequest')
以下是我自己使用它的方式:

post_data = { 
    "jsonrpc" : "2.0", "method": method, "params" : params, "id" : id }
return client.post('/api/json/', 
                    json.dumps(post_data), "text/json",            
                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')

执行一些json rpc。请注意,由于我传递的内容类型与默认值不同,因此我的数据将按post请求中的方式传递。

感谢@Eric_Fortin将我打开到标题,但它并不能解决我使用“client.post”的错误查询字典的问题。一旦我使用XMLHttpRequest头从POST更改为GET,我的查询字典就陷入困境。以下是当前的解决方案:

response = self.client.get(reverse('ajax_view'),
                           {'form':json_string},'json',
                           HTTP_X_REQUESTED_WITH='XMLHttpRequest')
这只是部分回答,因为此请求将更改服务器上的数据,应该是POST而不是GET

编辑:

下面是我测试中的最后一段代码,用于通过POST将JSON字符串传递到我的视图:

response = self.client.post(reverse('ajax_view'),
                            {'form':json.dumps(json_dict)})
现在,从视图打印显示查询字典的格式良好

<QueryDict: {u'form': [u'{"resource": {"status": "reviewed", "name": "Resource Test", "description": "Unit Test"}}']}>


我在与一位同事修补时找到了答案,删除了内容类型“json”,修复了格式错误的查询字典。正在测试的视图未使用或调用“HttpRequest.is_ajax()”,发送标头XMLHttpRequest对我的问题没有影响,尽管包含标题将构成良好的形式,因为这篇文章是一个ajax请求。

即使添加了标题“XMLHttpRequest”,我仍然会在查询字典的关键位置获得JSON字符串。删除第二个关于如何使用client.post的示例,我会将其标记为答案,第二个例子包含了我创建文章要解决的问题。嗯,对不起,第二个例子来自我的代码库,与我的json装饰器完美配合。请记住,我使用的json rpc与您的用例不同。如果它对其他人有帮助的话,我在使用django活塞API时发现,默认情况下,它拒绝“text/json”,但接受“application/json”。这是错误的,它也适用于post。尽管如此,即使更改了代码,使json字符串直接作为“post”方法的“data”参数提供,我的查询字典在我的“视图”中仍然被json字符串损坏。将方法从“post”更改为“get”,并将json_字符串作为字典的值引用,查询字典的结构正确。我支持我的回答。编辑我的回答来解释问题并详细说明解决方案。我承认发送标题是一种良好的形式,因为这篇文章是一个ajax请求,尽管包含标题对我的问题没有影响,这是查询字典的畸形。仅将json_字符串作为第二个参数提供给“client.post”方法会导致查询字典格式错误。当内容类型设置为“text/json”或仅设置为“json”时,“client.post”生成的查询字典的格式也不正确。