Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Flask会话属性在初始加载后丢失键入_Python_Session_Flask - Fatal编程技术网

Python Flask会话属性在初始加载后丢失键入

Python Flask会话属性在初始加载后丢失键入,python,session,flask,Python,Session,Flask,Flask的会话对象似乎正在将一个OrderedDict更改为一个dict。这很重要,因为我希望将当前用户可访问页面的相关信息存储在OrderedDict中,以帮助自动创建导航栏 我可能会昏昏欲睡,但我不认为我在这里写了任何会覆盖现有数据的东西,所以它只是毫无理由地转换为dict 下面是在会话对象中设置OrderedDict的代码 def safe_route(page_request): """Returns the correct page for the user's reques

Flask的
会话
对象似乎正在将一个
OrderedDict
更改为一个
dict
。这很重要,因为我希望将当前用户可访问页面的相关信息存储在
OrderedDict
中,以帮助自动创建导航栏

我可能会昏昏欲睡,但我不认为我在这里写了任何会覆盖现有数据的东西,所以它只是毫无理由地转换为
dict

下面是在
会话
对象中设置
OrderedDict
的代码

def safe_route(page_request):
    """Returns the correct page for the user's request.

    If a user requests a non-existent page, 404.
    If user wants a page they shouldn't see, but somehow
    they know about it, redirects to an access-denied page.

    If everything is in order, returns the page the user requests.
    """
    if page_request not in ordered_urls:
        return abort(404)      # early return for 404s

    # get current user and build their navi-dict.
    # this dict will be used to build the navibar in the webpage.
    if not 'registered' in session:
        CurrentUser = get_user(request)
        session['name'] = CurrentUser.name
        session['navi'] = build_user_navi(CurrentUser)
        session['registered'] = True
    if page_request in session['navi']:
        tpl = "/{}.html".format(page_request)
    else:
        # if here, the user requested a page that DOES exist
        # but they do NOT have access to. therefore, they are being
        # goons and require a trip to boxxytown
        tpl = "accessdenied.html"
    return render_template(tpl, on_page=page_request)
它检查以确保会话具有
'registered'
标志;如果没有,它将获取用户信息,然后调用
build\u user\u navi
,返回
orderedict
。这是第一次成功;初始页面加载显示navibar中的链接,这与我最初的意图相同。在随后的点击中,订单丢失,显然,
OrderedDict
上的类型也会丢失

在调用
render_template
之前,我在代码中添加了这一行,以查看它是否只是在更改我的类型:

print type(session['navi'])
果然,它在
之间切换


有没有一种方法可以正确地将一个
OrderedDict
存储为会话数据,或者有什么很好的理由可以解释为什么这只在第一次使用时才起作用,这应该会阻止我使用这种方法?

我怀疑会话对象被深度复制到了某个地方,然后,
OrderedDict
被复制为普通的
dict
。这可以通过咨询来源等方式找到


我想到的最简单的修复方法是存储一个简单的键值对列表,而不是一个
OrderedDict
,它同样容易迭代,并且在需要重复快速查找时很容易转换为任何
dict

会话中的所有数据都需要可序列化。
orderedict
是可序列化的,因为它是
dict
的子类,但JSON中没有有序dict,因此在序列化过程中会失去顺序

您可以重写以支持有序dict。这不是最方便的过程,因为您必须复制类的代码

from base64 import b64encode, b64decode
from collections import OrderedDict
from datetime import datetime
import uuid
from flask import json
from flask._compat import text_type, iteritems
from flask.debughelpers import UnexpectedUnicodeError
from markupsafe import Markup
from werkzeug.http import http_date, parse_date


class TaggedJSONSerializer(object):
    def dumps(self, value):
        def _tag(value):
            if isinstance(value, tuple):
                return {' t': [_tag(x) for x in value]}
            elif isinstance(value, uuid.UUID):
                return {' u': value.hex}
            elif isinstance(value, bytes):
                return {' b': b64encode(value).decode('ascii')}
            elif callable(getattr(value, '__html__', None)):
                return {' m': text_type(value.__html__())}
            elif isinstance(value, list):
                return [_tag(x) for x in value]
            elif isinstance(value, datetime):
                return {' d': http_date(value)}
            elif isinstance(value, OrderedDict):
                return {'OrderedDict': [[k, _tag(v)] for k, v in iteritems(value)]}
            elif isinstance(value, dict):
                return dict((k, _tag(v)) for k, v in iteritems(value))
            elif isinstance(value, str):
                try:
                    return text_type(value)
                except UnicodeError:
                    raise UnexpectedUnicodeError(u'A byte string with '
                        u'non-ASCII data was passed to the session system '
                        u'which can only store unicode strings.  Consider '
                        u'base64 encoding your string (String was %r)' % value)
            return value
        return json.dumps(_tag(value), separators=(',', ':'))

    def loads(self, value):
        def object_hook(obj):
            if len(obj) != 1:
                return obj
            the_key, the_value = next(iteritems(obj))
            if the_key == ' t':
                return tuple(the_value)
            elif the_key == ' u':
                return uuid.UUID(the_value)
            elif the_key == ' b':
                return b64decode(the_value)
            elif the_key == ' m':
                return Markup(the_value)
            elif the_key == ' d':
                return parse_date(the_value)
            elif the_key == 'OrderedDict':
                return OrderedDict(the_value)
            return obj
        return json.loads(value, object_hook=object_hook)
下面是一个新标签的演示。OrderedDict已正确反序列化

s = TaggedJSONSerializer()
data = OrderedDict((c, i) for i, c in enumerate('abcd'))
print(data)  # OrderedDict([('a', 0), ('b', 1), ('c', 2), ('d', 3)])
data = s.dumps(data)
print(data)  # {"OrderedDict":[["a",0],["b",1],["c",2],["d",3]]}
data = s.loads(data)
print(data)  # OrderedDict([('a', 0), ('b', 1), ('c', 2), ('d', 3)])
然后告诉您的应用程序使用此序列化程序

app.session_interface.serializer = TaggedJSONSerializer()

哦,老兄,我刚刚重构了
dicts
哈哈。这将教会我尝试新事物。JSON序列化是这里的关键——非常好的答案。这是一个导航栏的大量代码,所以我可能会支持其他海报的建议,使用不同的容器,但我真的很喜欢这个