【问题标题】:django development server hangs with firefox and chromedjango 开发服务器与 firefox 和 chrome 一起挂起
【发布时间】:2014-01-10 07:41:08
【问题描述】:

我在 windows 8.1 64 位上使用 django 开发服务器。我也在用 Tastypie。 mysql 版本为:5.5 (x86)。

我面临的问题是各种查询随机挂起。我在客户端使用 AJAX,但是当我使用 django 管理员时也会发生这种情况。我看到所有类似的问题都与 chrome 问题有关。但它也发生在 Firefox 上。 我的数据库是mysql。最近我安装了 SSD 驱动器,所以我所有的开发代码和数据库都在那个 SSD 上(不是我认为这应该有什么不同)

这里是在 Firebug 中看到的几个查询的示例。在这种情况下,第 4 次挂起(随机,有时是不同的)

GET id=1">http://127.0.0.1:8000/api/v1/financialmodel/?user_id=1 200 OK 1.33s jquery....min.js GET id=1">http://127.0.0.1:8000/api/v1/strategy/?user_id=1 200 OK 1.35s jquery....min.js(第6行) GET id=1">http://127.0.0.1:8000/api/v1/currency/?user_id=1 200 OK 1.4s jquery....min.js(第6行) 下一个查询卡住(但这是随机的,有时是另一个查询) GET id=1">http://127.0.0.1:8000/api/v1/account/?user_id=1 jquery....min.js(第 6 行) GET id=1">http://127.0.0.1:8000/api/v1/bankbranch/?user_id=1 200 OK 2.62s

我尝试使用以下方式运行服务器:

使用--nothread(或不使用)运行服务器

没有改变任何东西。

我尝试安装 //github.com/ashchristopher/django-concurrent-server 认为这可能会有所帮助,但同样的事情仍然随机挂在各种查询上。

如果我在 APTANA IDE 中使用调试器暂停服务器,我发现服务器位于:

SocketServer.py 第 155 行

def _eintr_retry(func, *args):
    """restart a system call interrupted by EINTR"""
    while True:
        try:
            return func(*args)
        except (OSError, select.error) as e:
            if e.args[0] != errno.EINTR:
                raise

有什么想法吗? 非常感谢!

这是 jquery-2.0.3 的 Ajax 代码中的一行

// Do send the request

// This may raise an exception which is actually

// handled in jQuery.ajax (so no try/catch here)

                xhr.send( options.hasContent && 
options.data || null );
            },

            abort: function() {

                if ( callback ) {

                    callback();

                }

            }

        };

    }

});

这是一个加载ui树的函数:

function loadAccountsTree() {
    $.getJSON("/api/v1/account/?user__id=" + userid, function(json) {
        // Extracting the required JSON structure from the entire response
        var tree = json.objects[0];
        $("#accounts-tree").jstree({
            "sort" : function() {
            },
            "json_data" : {
                "data" : tree
            },
            "types" : {
                "max_children" : 1,
                "types" : {
                    // Account type
                    "default" : {
                        "valid_children" : "none"
                    },
                    "folder" : {
                        "valid_children" : ["default", "folder"]
                    }
                }
            },
            "hotkeys" : {
                "return" : function() {
                    var hovered = $('#accounts-tree .jstree-hovered');
                    if (hovered.length) {
                        $("#accounts-tree").jstree("deselect_all");
                        $("#accounts-tree").jstree("select_node", hovered);
                    }
                }
            },
            "ui" : {
                select_multiple_modifier : false
            },
            "contextmenu" : {
                // Select node when right-clicking
                "select_node" : true,
                items : {// Could be a function that should return an object like this one
                    "ccp" : false,
                    "create" : {
                        "separator_before" : false,
                        "separator_after" : true,
                        "label" : "Create",
                        "action" : false,
                        "submenu" : {
                            "create_file" : {
                                "seperator_before" : false,
                                "seperator_after" : false,
                                "label" : "Account",
                                action : function(obj) {
                                    this.create(obj, "last", {
                                        "attr" : {
                                            "rel" : "default"
                                        }
                                    });
                                }
                            },
                            "create_folder" : {
                                "seperator_before" : false,
                                "seperator_after" : false,
                                "label" : "Folder",
                                action : function(obj) {
                                    this.create(obj, "last", {
                                        "attr" : {
                                            "rel" : "folder"
                                        }
                                    });
                                }
                            } // End of "create_folder" contextmenu function
                        }
                    }
                }
            },
            "plugins" : ["themes", "json_data", "ui", "hotkeys", "crrm", "dnd", "contextmenu", "types"]
        }).bind("before.jstree", function(e, data) {
            if (data.func === "remove") {
                var nodes = data.inst._get_node(null, true);
                for (var i = 0; i < nodes.length; i++) {
                    var node = nodes[i];
                    var nodeName = $(node).find('> a').text().substring(1);
                    if ($(node).find('> ul').length) {
                        alert('You need to delete all folders and accounts inside ' + nodeName + ' before deleting it.');
                        e.stopImmediatePropagation();
                        return false;
                    } else if (!confirm("Are you sure you want to delete " + nodeName + " ?")) {
                        e.stopImmediatePropagation();
                        return false;
                    }
                }
            }
        }).bind("loaded.jstree", function(event, data) {
            // Selecting top account
            data.inst.select_node('> ul > li:first');
            // Loading all assets for top account
            loadAccountAssets($("#accounts-tree > ul:first > li:first").attr("id"));
            loadCommissions($("#accounts-tree > ul:first > li:first").attr("id"));
        }).bind("create.jstree", function(e, data) {
            var newNode = data.rslt.obj;
            var verified = true;
            $(newNode).siblings().each(function(idx, listItem) {
                var siblingNode = $(listItem);
                if (newNode.attr("rel") !== siblingNode.attr("rel")) {
                    verified = false;
                    return false;
                }
            });
            var isFolder;
            if (data.rslt.obj.attr("rel") == 'default') {
                isFolder = 'false';
            } else {
                isFolder = 'true';
            }
            if (verified) {
                $.ajax({
                    type : 'POST',
                    // make sure you respect the same origin policy with this url:
                    // http://en.wikipedia.org/wiki/Same_origin_policy
                    url : '/api/v1/account/',
                    data : JSON.stringify({
                        'folder' : isFolder,
                        'user' : '/api/v1/user/' + userid + '/',
                        'parent' : '/api/v1/account/' + data.rslt.parent.attr("id") + '/',
                        'name' : data.rslt.name,
                        'type' : data.rslt.obj.attr("rel")
                    }),
                    contentType : "application/json",
                    dataType : 'json',
                    processData : false,
                    success : function(r) {
                        data.rslt.obj.attr("id", r.id);
                    },
                    error : function(xhr, textStatus, error) {
                        loadAccountsTree();
                        logErrors(xhr, textStatus, error);
                    }
                });
            } else {
                alert("Folders can contain either folders or accounts, not both at a time.");
                $(newNode).prev().addClass("jstree-last");
                $(newNode).remove();
            }
        }).bind("rename.jstree", function(e, data) {
            $.ajax({
                type : 'PATCH',
                url : '/api/v1/account/' + data.rslt.obj.attr("id") + '/',
                data : JSON.stringify({
                    "name" : data.rslt.new_name
                }),
                dataType : 'json',
                contentType : 'application/json',
                error : function(xhr, textStatus, error) {
                    loadAccountsTree();
                    logErrors(xhr, textStatus, error);
                }
            });
        }).bind("remove.jstree", function(e, data) {
            $.ajax({
                type : 'DELETE',
                url : '/api/v1/account/' + data.rslt.obj.attr("id") + '/'
            });
        }).bind("select_node.jstree", function(event, data) {
            var currentNode = data.rslt.obj;
            var ui_currency = ($('#usd').hasClass('active')) ? 'usd' : 'ils';
            var isFolder = currentNode.attr("rel") === "folder";
            if (isFolder) {
                $("#account-form").slideUp();
            } else {
                // The account is not a folder. Show account details and load its commissions.
                $("#account-form").slideDown();
                $("#account-name").attr("value", $(currentNode).text().substring(2));
                var bankId = $(currentNode).closest("li").data("bank_id");
                var accountBank = (bankId) ? bankId : "None";
                $("#bank").val(accountBank);
                $("#account-type").val($(currentNode).closest("li").data("account_type"));
                reloadAccountCommissions(currentNode.attr("id"));
            }
            reloadAccountAssets(isFolder, currentNode.attr("id"), ui_currency);
            var parents = currentNode.parents("li");
            var parentsList = currentNode.children("a").text().substring(1);
            parents.each(function(index) {
                parentsList = $(this).children("a").text().substring(1) + ' > ' + parentsList;
            });
            $("#account-title").text(currentNode.find("> a").text().substring(1) + " details");
            $("#account-breadcrumbs > p").text("Accounts: " + parentsList);
        }).bind("move_node.jstree", function(e, data) {
            data.rslt.o.each(function(i) {
                var valid = true;
                var currentNode = $(this);
                $(currentNode).siblings().each(function(idx, listItem) {
                    var siblingNode = $(listItem);
                    if (currentNode.attr("rel") !== siblingNode.attr("rel")) {
                        valid = false;
                        return false;
                    }
                });
                if (valid) {
                    $.ajax({
                        type : 'PATCH',
                        url : '/api/v1/account/' + currentNode.attr("id") + '/',
                        data : JSON.stringify({
                            "parent" : '/api/v1/account/' + data.rslt.np.attr("id") + '/'
                        }),
                        dataType : 'json',
                        contentType : 'application/json',
                        error : function(xhr, textStatus, error) {
                            loadAccountsTree();
                            logErrors(xhr, textStatus, error);
                        }
                    });
                } else {
                    $(data.rslt.op).append(currentNode);
                    $(currentNode).addClass("jstree-last");
                    alert("The parent folder can not contain folders and accounts at the same time.");
                }
            });
        });
    });
}

这是将所选帐户的所有资产加载到网格中的函数(当我检查服务器日志 200 已发回时,此网格有时会保持“正在加载...”,但在 Firebug 中是其中一个查询永无止境

function loadAccountAssets(accountid) {
    $("#pager-account-assets").empty();
    var ui_currency = ($('#usd').hasClass('active')) ? 'usd' : 'ils';
    $("#jqgrid-account-assets").empty().jqGrid({
        url : '/api/v1/assetgrid/?user__id=' + userid + '&account__id__in=' + accountid + '&ui_currency_code=' + ui_currency,
        datatype : 'json',
        ajaxGridOptions : {
            contentType : "application/json"
        },
        jsonReader : {
            repeatitems : false,
            id : "id"
        },
        colNames : ['Account', 'Place', 'Subtype', 'Issuer', 'Price linkage', 'Interest type', 'Return net', 'Return gross', 'Maturity term', 'Maturity date', 'Symbol', 'Update', 'Update hint', 'Value', 'Currency', 'Units', 'Price', 'Description', 'FinancialModel'],
        // 'Issuer', 'Price linkage', 'Interest type', 'Return net', 'Return gross', 'Maturity term', 'Maturity date', 'Financialmodel',
        colModel : [{
            name : 'Account',
            edittype : 'select',
            editoptions : {
                dataUrl : '/api/v1/account/?user__id=' + userid + '&folder=false',
                buildSelect : function(data) {
                    var response = $.parseJSON(data);
                    var s = '<select>';
                    $.each(response.objects, function(index, account) {
                        s += '<option value="' + account.resource_uri + '">' + account.data + '</option>';
                    });
                    return s + "</select>";
                }
            },
            stype : 'select'
        }, buildHiddenColumn('Place', 'place', true, false, 'resource_uri', 'name'), buildHiddenColumn('Subtype', 'subtype', true, false, 'resource_uri', 'name'), buildHiddenColumn('Issuer', 'issuer', true, false, 'resource_uri', 'name'), {
            name : 'price_linkage',
            hidden : true,
            editable : true,
            edittype : 'select',
            editoptions : {
                value : 'F:Foreign Currency;M:Madad;I:ILS'
            },
            stype : 'select',
            editrules : {
                edithidden : true
            }
        }, {
            name : 'Interest',
            hidden : true,
            editable : true,
            edittype : 'select',
            editoptions : {
                value : 'F:Fix;C:Changing;O:Other'
            },
            stype : 'select',
            editrules : {
                edithidden : true
            }
        }, {
            name : 'Return Net',
            editable : true,
            editrules : {
                edithidden : true
            },
            hidden : true,
            editoptions : {
                dataInit : function(element) {
                    $(element).attr("readonly", true);
                }
            }
        }, {
            name : 'Return Gross',
            editable : true,
            editrules : {
                edithidden : true
            },
            hidden : true,
            editoptions : {
                dataInit : function(element) {
                    $(element).attr("readonly", "readonly");
                }
            }
        }, {
            name : 'Maturity',
            hidden : true,
            editable : true,
            edittype : 'select',
            editoptions : {
                value : 'S:Short;M:Medium;L:Long'
            },
            stype : 'select',
            editrules : {
                edithidden : true
            }
        }, {
            name : 'MaturityDate',
            hidden : true,
            editable : true,
            formatter : "date",
            editoptions : {
                dataInit : function(el) {
                    setTimeout(function() {
                        $(el).datepicker({
                            dateFormat : "yy-mm-dd"
                        });
                    }, 200);
                }
            },
            formoptions : {
                rowpos : 1,
                colpos : 2
            },
            formatoptions : {
                newformat : "Y-m-d"
            },
            editrules : {
                edithidden : true
            }
        }, symbolColumn, {
            name : 'Update',
            edittype : 'select',
            editoptions : {
                value : 'A:Automatic;M:Manual'
            },
            formoptions : {
                rowpos : 2,
                colpos : 2
            },
            stype : 'select',
        }, {
            name : 'UpdHint',
            formoptions : {
                rowpos : 3,
                colpos : 2
            }
        }, {
            name : 'Value',
            width : 70,
            editable : false
        }, currencyColumn, {
            name : 'Units',
            width : 70,
            formoptions : {
                rowpos : 4,
                colpos : 2
            },
            editoptions : {
                dataInit : function(elem) {
                    setTimeout(function() {
                        // It must be an integer
                        $(elem).numeric(false, function() {
                            alert("Integers only");
                            this.value = "";
                            this.focus();
                        });
                    }, 100);
                }
            }
        }, {
            name : 'Price',
            width : 70,
            formoptions : {
                rowpos : 5,
                colpos : 2
            },
            editoptions : {
                dataInit : function(elem) {
                    setTimeout(function() {
                        $(elem).numeric();
                    }, 100);
                }
            }
        }, {
            name : 'Description',
            formoptions : {
                rowpos : 6,
                colpos : 2
            },
            width : 200
        }, {
            name : 'FinancialModel',
            edittype : 'select',
            formoptions : {
                rowpos : 7,
                colpos : 2
            },
            editoptions : {
                dataUrl : '/api/v1/financialmodel/?user__id=' + userid,
                buildSelect : function(data) {
                    var response = $.parseJSON(data);
                    var s = '<select><option value="">None</option>';
                    $.each(response.objects, function(index, financialmodel) {
                        s += '<option value="' + financialmodel.resource_uri + '">' + financialmodel.data + '</option>';
                    });
                    return s + "</select>";
                }
            },
            stype : 'select'
        }],
        cmTemplate : {
            editable : true,
            width : 100
        },
        ondblClickRow : function() {
            var rowid = $("#jqgrid-account-assets").getGridParam('selrow');
            $('#jqgrid-account-assets').jqGrid('editRow', rowid, {
                keys : true,
                dataType : 'json',
                url : '/api/v1/assetgrid/' + encodeURIComponent(rowid) + '/',
                mtype : 'PATCH'
            });
        },
        serializeRowData : function(data) {
            return serializeAssetData(data);
        },
        ajaxRowOptions : {
            contentType : "application/json"
        },
        width : 835,
        shrinkToFit : false,
        gridview : true,
        height : "auto",
        autoencode : true,
        loadonce : true,
        rowNum : 10,
        rowList : [10, 20, 30],
        pager : "#pager-account-assets",
        viewrecords : true,
    }).jqGrid("navGrid", "#pager-account-assets", {
        search : false,
        refresh : false
    },
    // edit options
    {
        closeAfterEdit : true,
        mtype : "PUT",
        serializeEditData : function(data) {
            return serializeAssetData(data);
        },
        onclickSubmit : function(params, postdata) {
            params.url = '/api/v1/assetgrid/' + encodeURIComponent(postdata[this.id + "_id"]) + '/';
        },
        ajaxEditOptions : {
            contentType : "application/json",
            dataType : "json"
        },
        afterSubmit : function(response, postdata) {
            $('#jqgrid-account-assets').setGridParam({
                datatype : 'json'
            }).trigger('reloadGrid');
            return [true, '', false];
        },
        beforeShowForm : function(form) {
            centerDialog($("#editmodjqgrid-account-assets"));
        }
    },
    // add options
    {
        closeAfterAdd : true,
        mtype : "POST",
        serializeEditData : function(data) {
            return serializeAssetData(data);
        },
        onclickSubmit : function(params, postdata) {
            params.url = '/api/v1/assetgrid/';
        },
        afterSubmit : function(response, postdata) {
            $('#jqgrid-account-assets').setGridParam({
                datatype : 'json'
            }).trigger('reloadGrid');
            return [true, ''];
        },
        ajaxEditOptions : {
            contentType : "application/json",
            dataType : "json"
        },
        beforeShowForm : function(form) {
            centerDialog($("#editmodjqgrid-account-assets"));
        }
    },
    // delete options
    {
        // Delete parameters
        mtype : "DELETE",
        serializeDelData : function() {
            return "";
        },
        onclickSubmit : function(params, postdata) {
            params.url = '/api/v1/assetgrid/' + encodeURIComponent(postdata) + '/';
        },
        beforeShowForm : function(form) {
            centerDialog($("#delmodjqgrid-account-assets"));
        },
        afterSubmit : function(response, postdata) {
            $('#jqgrid-account-assets').setGridParam({
                datatype : 'json'
            }).trigger('reloadGrid');
            return [true, ''];
        }
    });
}

【问题讨论】:

  • 你能分享你的查询或你的ajax调用吗?问题可能就在那里......
  • yuvi,我认为你是对的。问题可能出在 Ajax 代码中。我计算了 runserver 日志中的查询,并意识到显示卡在 firebug 中的查询到达服务器并返回 200。由于某种原因,Ajax 代码卡住了。呼叫来自 jquery-2.0.3 行 7845。我在此处包含了相关的代码。由于其他人正在编写客户端,除非您有一些线索,否则我可能不得不寻求他们的帮助。
  • 我想我找到了线索……它在 jquery.jqGrid.js 文件中。以下帖子stackoverflow.com/questions/1470333/jqgrid-stuck-on-loading 谈到了它。我必须检查一下
  • 您能分享您的 django 查询以及其余的客户端代码吗?即使您认为一切正常,您也很可能会遗漏一些东西
  • 谢谢。我添加了加载带有一些帐户信息的树的功能。以及为树中所选帐户加载资产网格的函数

标签: jquery mysql django


【解决方案1】:

我一直在我的 django 项目中使用 sweetpie。这工作非常顺利,我没有这样的问题。 要调试这个首先确定问题出在哪里。请求是否到达服务器,数据库查询是否花费了太多时间,数据库连接是否中断等以了解是数据库导致问题还是您的 django 代码、tastepie 或 ajax 调用。

开发服务器日志,我想你已经知道了。把它的输出贴在这里,以便我们更好地理解。

查看mysql日志:关注How to see log files in MySQL?

您正在使用浏览器调用这些 api 然后安装 django-debug-toolbar,它会获取一些信息。尝试 curl 代替浏览器:

curl http://127.0.0.1:8000/api/v1/account/?user_id=1

另请参阅。 http://django-tastypie.readthedocs.org/en/latest/debugging.html

P.S:目前我的声誉很低,我无法发表评论。

【讨论】:

  • 感谢您的回复。关于 SQL 日志:我检查了 sql server 日志。查询正确到达 SQL 服务器。 sql.err 文件也没有错误。在我使用 FireBug 的浏览器上,它显示的查询没有什么特别的,除了它永远不会结束(但每次都是不同的查询,这就是为什么我认为它与服务器相关)。我在 Linux 上(在我的托管服务中)运行了相同的代码,并且运行良好。所以它以某种方式与 Windows 相关。
  • 在 Windows 上分享您的查询和您的 mysql 版本。早期的 mysql 中存在一些与您的情况相似的错误。
  • 我分享了我的一些疑问。 mysql版本为:5.5(x86),windows 8.1 64位。
猜你喜欢
  • 1970-01-01
  • 2018-10-05
  • 2012-02-21
  • 1970-01-01
  • 2016-06-06
  • 1970-01-01
  • 2018-03-06
  • 2019-10-26
  • 2011-06-27
相关资源
最近更新 更多