2011-01-25 70 views
10

我想为某些Django json_view视图编写一些单元测试,并且无法将json_string传递给视图。我昨天发布了一个相关的问题,关于从JS传递json字符串到Django视图,问题是在我的JS中,我只是传递json字符串,我需要传递字符串作为对象的属性,因为我没有做到这一点,字符串被视为结果查询字典的关键。我又遇到了类似的问题,只不过这次它是对Django View进行Django单元测试。这里是我的代码的简化版本,它产生相同的结果。单元测试Django JSON查看

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(): 
     ... 

这是在测试运行时的两个打印语句产生什么。该json_string是

{"resource": {"type": "book", "author": "John Doe"}} 

和查询字典看起来像

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

我与JS和AJAX总新手,所以不用担心伤害了我的自尊,答案很可能是在附近,所以可以跳起来咬我。

回答

9

最后编辑

我最初说,头HTTP_X_REQUESTED_WITH='XMLHttpRequest'在内线通话必须的,但是这是目前假,而在测试中。该头文件对于csrf中间件是必需的,但在测试中csrf被禁用。但是,即使中间件禁用了csrf,我仍然认为这是一个很好的做法,因为大多数JavaScript库在执行ajax时已经默认通过此标头。另外,如果另一段未被禁用的代码使用is_ajax方法,则不需要花费数小时调试unittest以确定头文件丢失。

问题与内容类型有关,因为当django获取的值不同于text/html时,它不使用默认的后置数据处理来格式化数据,如在查询中: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。请注意,由于我传递的是不同于默认值的内容类型,因此我的数据按原样传递到了发布请求中。

+1

即使添加头“XMLHttpRequest”,我仍然在查询字典的关键位置获得JS​​ON字符串。 – snarkyname77 2011-01-25 15:04:47

+0

删除您如何使用client.post的第二个示例,并将其标记为答案,第二个示例包含我创建要解析的帖子的问题。 – snarkyname77 2011-01-28 17:40:21

4

非常感谢@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"}}']}> 

我找到了答案,而我的同事一个修修补补,去除CONTENT_TYPE“JSON”固定格式不正确的查询字典。正在测试的视图没有使用或调用'HttpRequest.is_ajax()',发送头XMLHttpRequest'对我的问题没有影响,尽管包含头将构成良好的形式,因为这篇文章是一个Ajax请求。