单元测试的Django JSON查看单元测试、Django、JSON

2023-09-10 13:26:58 作者:光芒万照好菇凉

我试着写一些单元测试一些Django的json_view意见,我无法传递json_string到视图。我昨天发布了一个相关的问题有关从JS传递一个JSON字符串到Django的观点,问题是,在我的JS,我只是路过,我需要被路过的字符串作为一个对象的属性JSON字符串,因为我在没有做到这一点的字符串正在采取的密钥生成的查询字典。我再有,只是这一次它是形成一个Django单元测试Django的视图类似的问题。这里是我的code的简化版本,它会产生相同的结果。

I'm trying to write some unit tests for some Django json_view views and I'm having trouble passing the json_string to the view. I posted a related question yesterday about passing a json string to a Django view from the JS, the issue was that in my JS I was just passing the json string where I needed to be passing the string as the attribute of an object, because I was failing to do this the string was being taken as the key for the resulting query dict. I'm having a similar problem again except that this time it is form a Django unit test to the Django View. Here is a simplified version of my code which produces the same result.

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_string是

Here is what the two print statements produce when the test is run. The json_string is

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

和查询字典的样子

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

我总新手用JS和Ajax,所以不用担心伤害了我的自尊,答案很可能是如此接近,它可以跳起来咬我。

I'm total newbie with JS and ajax, so don't worry about hurting my pride, the answer is probably so close it could jump up and bite me.

推荐答案

最后修改

我原来说的头 HTTP_X_REQUESTED_WITH ='XMLHtt prequest 是必要的,后调用,但是这是目前在测试中错误的时间。这头是必要的CSRF中间件,但CSRF在测试中被禁用。不过,我仍然认为这是一个很好的做法是在测试即使中间件禁用,因为大多数的JavaScript库做阿贾克斯的时候就已经通过这个头默认情况下,CSRF。另外,如果另一块code未禁用用不完的is_ajax方法,你不会需要调试单元测试了几个小时,以找出这个头不见了。

I originally stated that header HTTP_X_REQUESTED_WITH='XMLHttpRequest' was necessary in the post call but this is currently false while in tests. This header is necessary for the csrf middleware but csrf is disabled in tests. However, I still believe it is a good practice to put in test even if middleware disables csrf since most javascript library already pass this header by default when doing ajax. Also, if another piece of code that is not disabled ever use the is_ajax method, you won't need to debug your unittest for hours to figure out that the header was missing.

现在的问题是与内容类型,因为当Django的获取一个值在那里比的text / html 不同,它不使用默认的数据后处理这是格式化你的数据,如在一个查询:键入=书和放大器;笔者= ​​JOHNDOE 为例。

The problem is with the content-type because when django gets a value in there that is different than text/html, it doesn't use the default post data handling which is to format your data like in a query: type=book&author=JohnDoe for example.

然后固定code是:

response = self.client.post(reverse('ajax_view'),
                            {'form':json_string}, 
                            HTTP_X_REQUESTED_WITH='XMLHttpRequest')

下面是我如何使用它自己:

Here's how I'm using it myself:

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请求。

to do some json-rpc. Notice that since I pass a different content-type than the default value, my data is passed as is in the post request.