jquery - Django 开发服务器在 Firefox 和 Chrome 上挂起

标签 jquery mysql django

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

我面临的问题是各种查询随机挂起。我在客户端使用 AJAX,但当我使用 django admin 时也会发生这种情况。我看到所有类似的问题都与 chrome 问题有关。但在 Firefox 上也会发生这种情况。 我的数据库是mysql。最近我安装了 SSD 驱动器,因此我所有的开发代码和数据库都位于该 SSD 上(我认为这不会有任何区别)

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

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 (line 6) GET id=1">http://127.0.0.1:8000/api/v1/currency/?user_id=1 200 OK 1.4s jquery....min.js (line 6) the next query get stuck (but this is random sometime it is another query) GET id=1">http://127.0.0.1:8000/api/v1/account/?user_id=1 jquery....min.js (line 6) GET id=1">http://127.0.0.1:8000/api/v1/bankbranch/?user_id=1 200 OK 2.62s

我尝试运行服务器:

runserver with --nothread (or without)

没有改变任何东西。

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

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

SocketServer.py line 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.");
                }
            });
        });
    });
}

这是将所选帐户的所有 Assets 加载到网格中的函数(该网格有时保持“正在加载...”,当我检查服务器日志时,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, ''];
        }
    });
}

最佳答案

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

Development server log, I suppose you know already. paste it's output here so that we can get more understanding.

To check mysql log : follow How to see log files in MySQL?

You are using browser to call these api then install django-debug-toolbar, it will fetch some info. try curl also instead of browser :

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

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

P.S:我无法发表评论,因为我现在的声誉很低。

关于jquery - Django 开发服务器在 Firefox 和 Chrome 上挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21038634/

相关文章:

javascript - 使用 JavaScript 启用 CSS 幻灯片自动播放

javascript - 追加/添加到容器

mysql - 普通字段像 Zerofill 字段一样返回

django - 在 Django 模板中定义 "global variable"

django - 具有复杂查询的 REST API

python - 两个类 : one for the django model and one for representing the data outside of django

javascript - 没有 jQuery 的 .html() 和 .append()

mysql - 使用 float mysql

mysql - sql消息表查询

jquery - 取消选择后无法再次选择选项