在Django项目中通过javascript将数据写入cookie

时间:2014-02-08 00:34:07

标签: javascript django cookies

在我的Django项目中,有一个名为Workspace的MPTT模型(“Dossier”,法语)。与计算机中的目录一样,工作空间可以嵌套在一起。

Workspaces view

然后

工作区显示给用户,如上一个屏幕截图所示,就像一棵树。

默认情况下,所有工作区都会展开。当用户单击“ - ”符号时,子工作空间消失,相反,单击“+”时。这是由javascript处理的。

这很有效。但是,我希望在用户刷新页面时保存树状态,这样他就不需要再次展开/折叠所有内容。

我知道我可以通过ajax执行此操作:单击“ - ”或“+”将向服务器发送请求,将工作空间的pk和用户存储在具有状态的数据库中。这对我来说似乎非常复杂,并且它不适用于匿名用户。

更好的想法是用cookie处理这个问题,但我显然在编写javascript代码时犯了一些愚蠢的错误。这是我到目前为止:

$( document ).ready(function() {

    // from http://ppk.developpez.com/tutoriels/javascript/gestion-cookies-javascript/
    // these are sample functions to write/read cookies took from a tutorial

    function createCookie(name,value,days) {
        if (days) {
            var date = new Date();
            date.setTime(date.getTime()+(days*24*60*60*1000));
            var expires = "; expires="+date.toGMTString();
        }
        else var expires = "";
        document.cookie = name+"="+value+expires+"; path=/";
    }

    function readCookie(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for(var i=0;i < ca.length;i++) {
            var c = ca[i];
            while (c.charAt(0)==' ') c = c.substring(1,c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
        }
        return null;
    }

    function eraseCookie(name) {
        createCookie(name,"",-1);
    }


    function arrayToCookie(array){ // convert an array to cookie format (coma separated list)
        return array.join(',');
    }
    function cookieToArray(cookie){
        return cookie.split(','); // convert a coma-separated cookie to an array
    }


    var expanded_workspaces_cookie_name = "expandedWorkspaces";

    // create the cookie if it does not exists
    // The cookie is basically a list of workspaces id that are expanded, written like this : "1,3,12,157"
    function initExpandedCookie(){
        console.log("init cookie");
        console.log('read',document.cookie, readCookie(expanded_workspaces_cookie_name));
        console.log(typeof($.cookie(expanded_workspaces_cookie_name)));

        if (!readCookie(expanded_workspaces_cookie_name)) {
            console.log("new cookie");
            createCookie(expanded_workspaces_cookie_name,'', 365);
        }
        else {
            console.log("cookie already exists");
        }
    }

    initExpandedCookie();

    function setExpandedWorkspaceToCookie(id, add){
        console.log("id =", id, typeof(id), id.length);
        var w = readCookie(expanded_workspaces_cookie_name);
        console.log('Value of old cookie',document.cookie);
        var s = cookieToArray(w);
        console.log("Id array before", s);
        if (add === true) { // Add the id to the list of expanded workspaces, in cookie
            console.log('Add workspace to expanded list');
            s.push(id);
            console.log("Id array after add", s);
        }
        else { // remove the id from the list of expanded workspaces, in cookie
            console.log('Remove workspace from expanded list');
            s.splice(s.indexOf(id));
        }
        console.log("Id array after", s);
        eraseCookie(expanded_workspaces_cookie_name); // empty existing cookie
        console.log('Values to insert into cookie', arrayToCookie(s));
        createCookie(expanded_workspaces_cookie_name, arrayToCookie(s), 365); // add id lists to cookie
        console.log('Value of new cookie',document.cookie );

    }
    function collapse(e, update_cookie) {
        e.addClass("collapsed");
        e.removeClass("expanded");
        e.find('ul.children').hide();
        if (update_cookie==true){
            setExpandedWorkspaceToCookie($(e).attr('id'), false);
        }
    }
    function expand(e, update_cookie) {
        e.addClass("expanded");
        e.removeClass("collapsed");
        e.find('ul.children').show();
        if (update_cookie==true){
            setExpandedWorkspaceToCookie($(e).attr('id'), true);
        }
    }

    $('#workspaces.widget .parent.expanded').each( function(index){
        expand($(this)); // Set up already expanded workspaces, so don't update cookie
    });
    $('#workspaces.widget .parent.collapsed').each( function(index){
        collapse($(this)); // Set up already collapsed workspaces, so don't update cookie
    });
    $('#workspaces.widget .parent .collapse').click(function() {
        collapse($(this).closest('.parent'), true); // Trigger when clicking on "-", so update cookie
    });
    $('#workspaces.widget .parent .expand').click(function() {
        expand($(this).closest('.parent'), true); // Trigger when clicking on "-", so update cookie
    });

}); 

当我在浏览器中测试它(在某些工作区上折叠/展开)时,javascript控制台输出:

init cookie 
read expandedWorkspaces=; csrftoken=bnR6E6s2CtjCTYEyl5reGTijR3mFXdLF  
string 
new cookie 
id = 220 string 3 
Value of old cookie csrftoken=bnR6E6s2CtjCTYEyl5reGTijR3mFXdLF; expandedWorkspaces= 
Id array before [""] 
Remove workspace from expanded list 
Id array after [] 
Values to insert into cookie  
Value of new cookie csrftoken=bnR6E6s2CtjCTYEyl5reGTijR3mFXdLF; expandedWorkspaces= 
id = 220 string 3 
Value of old cookie csrftoken=bnR6E6s2CtjCTYEyl5reGTijR3mFXdLF; expandedWorkspaces= 
Id array before [""] 
Add workspace to expanded list 
Id array after add ["", "220"] 
Id array after ["", "220"] 
Values to insert into cookie ,220 
Value of new cookie csrftoken=bnR6E6s2CtjCTYEyl5reGTijR3mFXdLF; expandedWorkspaces=,220

我尝试将扩展工作区列表作为逗号分隔列表存储在cookie中。出于某种原因,它在列表中插入一个空字符串。此外,在扩展工作空间时,不是在cookie的末尾添加ID,而只是用它的ID替换整个cookie。

您可以在此处测试它(在Javascript控制台处于打开状态):http://kii.eliotberriot.com/test/items

此外,还有一种更有效的方法来处理我正在做的事情吗?

感谢您的帮助,请告诉我您是否需要更多信息!

1 个答案:

答案 0 :(得分:3)

更好的方法是使用Django Sessions,而不是在javascript中处理Cookie。

会话可以由数据库或Cookies支持,您可以在会话中存储任意对象。

每次展开/折叠工作区时,向视图发出ajax请求,以逗号分隔的格式显示扩展工作区的ID。

def handle_ws_expand(request):
    request.session['EXPANDED_WORKSPACES'] = request.REQUEST.get("EXPANDED_WS_IDS", "").split(",")
    return HttpResponse('Success')

然后,在主页面视图中,输入if条件以检查是否需要扩展工作区。

def my_main_view(request):
    # Code to get Workspaces
    for ws in workspaces:
        if ws.pk in request.session['EXPANDED_WORKSPACES']:
            ws.isExpanded = True

OR,直接在模板中处理:

{% for ws in workspaces %}
    {% if ws.pk in request.session.EXPANDED_WORKSPACES %}
        # Code to expand Workspace
    {% endif %}
{% endfor %}

使用会话的最佳部分是,在多个登录用户的情况下,将分别为每个用户维护工作空间的状态。这也适用于已注销的用户。