gpt4 book ai didi

python - Flask session 属性在初始加载后丢失类型

转载 作者:行者123 更新时间:2023-11-28 16:31:17 27 4
gpt4 key购买 nike

flask 的 session对象似乎正在改变 OrderedDict进入dict .这很重要,因为我曾希望将有关当前用户可访问页面的信息存储在 OrderedDict 中。协助自动创建导航栏。

我可能睡眼惺忪,但我不认为我在这里写了任何会覆盖现有数据的东西,所以 AFAICT 它只是转换为 dict没有明显的原因。

这是设置 OrderedDict 的代码在session对象。

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)

它检查以确保 session 具有 'registered'旗帜;如果不是,它会获取用户信息,然后调用 build_user_navi返回 OrderedDict .这是第一次工作;初始页面加载显示导航栏中的链接,正如我最初预期的那样。在随后的点击中,订单丢失了,OrderedDict 上的类型显然也是如此。 .

render_template 之前打电话,我在代码中添加了这一行,看看它是否只是在改变我的类型:

print type(session['navi'])

果然,它在<class 'collections.OrderedDict'>之间切换和 <type 'dict'> .

是否有正确存储 OrderedDict 的方法?作为 session 数据,或者是否有一些非常好的理由为什么这只在第一次工作时应该阻止我使用这种方法?

最佳答案

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

您可以覆盖 how Flask serializes the session为了支持有序的字典。这不是最方便的过程,因为您必须复制类的代码。

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()

关于python - Flask session 属性在初始加载后丢失类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31683426/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com