我正在为此扯头发。我正在Django 1.3中开发一个web应用程序(最近从1.2.5升级,希望这可以解决我的错误),我在其中一种观点中遇到了一个奇怪的错误。

该视图被称为来自客户端的AJAX请求。如果我将视图称为GET请求,那么一切都很好。如果我将其作为无数据的POST请求来调用,那么一切都很好。但是,如果我将其称为POST并实际上包含数据(无论该数据是什么),则Django将返回空白页。

善于修补,我发现我可以从视图中打印并在调试控制台中获取输出,因此我开始工作,发现了这种奇怪的奇怪之处:

c = Character.objects.get(id = int(character))

这是该视图中处理模型的第一行代码。打印表明,不仅字符是一个合理的值(它是请求传递的ID),而且c最终以正确的数据库记录结尾。无论如何,如果调用该行,则Django的请求输出为zilch。娜达没有。

如果我在对模型进行任何操作之前提早返回,则Django会正确呈现其余请求。对模型执行某些操作会导致发送响应200,但是似乎省略了该内容。

这似乎仅在发送POST数据时发生,无论该POST数据是被读取还是以任何方式使用。我对此完全感到困惑。我将在这里发布我的代码,并希望这里的某个人对幕后发生的黑魔法有所了解。

这是视图本身,直接从urls.py调用:

@csrf_exempt
def ajax_update(request, character):
    #determine the timestamp to send the client *before* polling
    #the database

    update_time = int(time.time())

    #grab each update... thingy as json, and put it all together
    output = {
        "events": current_events(request, character, "default"),
        "character": character,
        "update_time": update_time,
    }

    return HttpResponse(json.dumps(output), mimetype = "application/json")


这是current_events代码,其中包含上述行:

def current_events(request, character, type = "default", timestamp = 0):
    '''
    purpose: grab the last 3 days worth of events, or the last 10 events,
    whichever is a larger list.
    '''

    #TODO: actually do something with timestamp
    c = Character.objects.get(id=int(character))

    #DEBUG: What on earth is going on here?
    print c

    #TODO: See if this can be optimized into a single query
    event_links = EventLink.objects.filter(viewer=c)
    events = Event.objects.filter(id__in=event_links.values('event')).order_by('timestamp')

    t = loader.get_template('ajax/world-events.html')

    output = []

    for event in events:
        revisions = Event.objects.filter(original_event=event.id).order_by('timestamp')

        display_message = event.message

        history = []
        if len(revisions):
            history.append(event) #first item in the history is the original event
            history.extend(revisions)
            display_message = history[-1].message

        output.append({
            "id": event.id,
            "writer": event.writer.id,
            "type": event.type,
            "timestamp": int(time.mktime(event.timestamp.timetuple())),
            "message": t.render(RequestContext(request, {"event_text": display_message, "event": event, "history": history}))
        })

    return output


最后,这是CoffeeScript,它使用jQuery从客户端调用代码:

auto_refresh_abort = 0
last_server_timestamp = 0
window.update_display = ->
    #ajax call to grab events from the server
    $.ajax
        type: 'POST'
        url: "/ajax/update/"+window.active_character
        data:
            "last_update": last_server_timestamp
        dataType: "json"
        success: (output) ->
            auto_refresh_abort = 0
            update_character_log output.events
        error: (XMLHttpRequest, textStatus, errorThrown) ->
            auto_refresh_abort += 1
            console.log XMLHttpRequest

    return null


如果您认为有帮助(已经很多),我可以发布所需的任何其他代码示例,例如模型代码本身。我可以确认在我的测试用例中正在查找的Character是否确实存在,并且它只是一个标准的Django ID,我对此没有做任何奇怪的事情。

提前致谢。

更新:根据要求,以下是输出应包含的示例:

{'update_time': 1305984080, 'character': u'1', 'events': /*snip*/}


我已经验证了代码执行一直在进行,并且传递给HttpResponse的输出确实包含此数据。对于傻笑,我在轮询字符的行后插入了一个返回值“ TASTY”,因此输出的数据应为:

{'update_time': 1305984080, 'character': u'1', 'events': 'TASTY'}


并确认这有效。我可以在HttpRequest之前“打印输出”到调试控制台,并显示出来。

如果我注释掉处理Character的行,我的浏览器将接收到该数据作为请求的内容。另外,如果我将代码保持原样并且根本不发送POST数据,则浏览器将接收正确的数据。失败的特定情况是当我从客户端发送POST数据后操纵模型时-在这种情况下,浏览器接收的HTTP头完全相同,但没有内容。它收到的标头是:

Content-Type:application/json
Date:Sat, 21 May 2011 13:29:38 GMT
Server:WSGIServer/0.1 Python/2.6


但没有提供实际的内容。

最佳答案

这将是一个答案。它是一种方法论,因此您一开始就不会遇到此问题,但是如果发生问题,也可以使用它来调试问题。


首先使用curl或firefox REST客户端plugin创建请求:
然后,您编写响应代码,返回硬编码的虚拟对象响应,其中涉及几种情况(或所有用例)。因此,您的character和current_events函数仅返回您知道正确的“虚拟”对象。
您使用REST客户端(或更正式的测试)来验证响应是否正常工作。
您编写您的客户端Ajax代码,并验证它是否与虚拟输出兼容。
您可以将虚拟对象调用重构为调用对象本身的函数(可以很快验证它们是否以应有的方式返回对象。


您可以使用它来有效地调试程序,否则,您只是在猜测程序的哪个部分正在工作,并且它很容易在很多地方失败。

10-04 23:32
查看更多