【发布时间】:2020-02-12 02:47:16
【问题描述】:
我有一个简单的看法
def foo(request):
card = Card.objects.latest(datetime)
request.session['card']=card
对于上面的代码,我得到了错误
"<Card: Card object> is not JSON serializable"
Django 版本 1.6.2。我究竟做错了什么 ?
【问题讨论】:
我有一个简单的看法
def foo(request):
card = Card.objects.latest(datetime)
request.session['card']=card
对于上面的代码,我得到了错误
"<Card: Card object> is not JSON serializable"
Django 版本 1.6.2。我究竟做错了什么 ?
【问题讨论】:
在会话中,我只存储对象主键:
request.session['card'] = card.id
当从会话中加载卡片时,再次获取卡片:
try:
card = Card.objects.get(id=request.session['card'])
except (KeyError, Card.DoesNotExist):
card = None
如果会话中没有card 条目或特定卡不存在,则将card 设置为None。
默认情况下,会话数据为serialised to JSON。您还可以provide your own serializer,它知道如何存储card.id 值或其他一些表示形式,并在反序列化时再次生成您的Card 实例。
【讨论】:
有两种简单的方法可以做到这一点。
【讨论】:
不幸的是,如果对象不是数据库对象而是某种其他类型的对象(例如 datetime 或对象类 Foo(object): pass that is not a database model object),则建议的答案不起作用。
当然,如果对象碰巧有一些 id 字段,您可以将 id 字段存储在数据库中并从那里查找值,但通常它可能没有这么简单的值,唯一的方法是转换数据以您可以读取该字符串并根据字符串中的信息重建对象的方式进行字符串化。
在 datetime 对象的情况下,由于简单的 datetime 对象可以通过简单地不打印任何内容来打印出格式 %Z,但如果没有任何内容,strptime 对象无法读取格式 %Z,这使情况变得更加复杂。除非那里有有效的时区规范,否则会阻塞 - 因此,如果您有一个可能包含或可能不包含 tzinfo 字段的日期时间对象,您真的必须使用 %Z 执行 strptime 两次,然后如果它在没有 %Z 的情况下阻塞。这很愚蠢。由于 datetime 对象具有 fromtimestamp 函数但没有 totimestamp 函数统一生成 fromtimestamp 将读取的时间戳,这一事实变得更加愚蠢。如果有一种格式代码会产生我一次又一次没有找到的时间戳编号,那么 strftime/strptime 会受到如上所述它们不是对称的事实的影响。
【讨论】:
@Martijn 是或可能是将对象保存在会话变量中的正确方法。
但是这个问题通过回到 Django 1.5 得到了解决。所以这个问题是专门针对 django 1.6.2 的。
希望这会有所帮助。
【讨论】:
settings.py。
对象不能存储在 Django 1.6 或更高版本的会话中。 如果您不想更改 cookie 值(对象)的行为,您可以在此处添加字典。这可以用于非数据库对象,如类对象等。
from django.core.serializers.json import DjangoJSONEncoder
import json
card_dict = card.__dict__
card_dict .pop('_state', None) #Pop which are not json serialize
card_dict = json.dumps(card_dict , cls=DjangoJSONEncoder)
request.session['card'] = card_dict
希望对你有帮助!
【讨论】:
SESSION_SERIALIZER。
-->永远不要做这样的事情!
Django 使用 session 和 ctypes:请阅读下面的Martijn Pieters 解释评论。
class MyObject:
def stuff(self):
return "stuff..."
my_obj = MyObject()
request.session['id_my_obj'] = id(my_obj)
...
id_my_obj = request.session.get('id_my_obj')
import ctypes
obj = ctypes.cast(id_my_obj, ctypes.py_object).value
print(obj.stuff())
# returns "stuff..."
【讨论】:
my_obj 被垃圾收集,这不仅不起作用,而且会导致内存损坏。 id(my_obj) 可以轻松地 指向已经被其他东西使用的任意一块内存,但是在使用ctypes.cast().value 的那一刻,Python 将尝试更新该“对象”的引用计数,因此开始写入那块内存。