我有一个简单的观点
def foo(request): card = Card.objects.latest(datetime) request.session['card']=card
对于上面的代码,我得到了错误
"<Card: Card object> is not JSON serializable"
Django版本1.6.2.我做错了什么?
dvtswwa31#
在会话中,我只存储对象主键:
request.session['card'] = card.id
以及当从会话加载卡时,通过以下方式再次获得卡:
try: card = Card.objects.get(id=request.session['card']) except (KeyError, Card.DoesNotExist): card = None
如果会话中没有card条目或者特定的卡不存在,则将card设置为None。默认情况下,会话数据被序列化为JSON。您也可以提供自己的序列化器,它知道如何存储card.id值或其他表示,并在反序列化时再次生成您的Card示例。
card
None
card.id
Card
gywdnpxw2#
不幸的是,如果对象不是数据库对象,而是其他类型的对象(例如,日期时间或对象类Foo(object)),则建议的答案不起作用:不是数据库模型对象的传递。当然,如果对象碰巧有一些id字段,你可以将id字段存储在数据库中,并从那里查找值,但通常它可能没有这样一个简单的值,唯一的方法是将数据转换为字符串,这样你就可以读取该字符串,并根据字符串中的信息重建对象。在datetime对象的情况下,这会变得更加复杂,因为尽管简单的datetime对象可以通过不打印任何内容来打印出格式%Z,但strptime对象无法读取格式%Z(如果没有任何内容),它将阻塞,除非那里有有效时区规范-所以如果你有一个datetime对象,可能包含也可能不包含tzinfo字段,你真的必须做两次strptime,一次用%Z,然后如果它没有%Z就阻塞了。这很愚蠢。更愚蠢的是,datetime对象有一个fromtimestamp函数,但没有一个totimestamp函数,该函数统一产生一个fromtimestamp将读取的时间戳。如果有一个格式代码产生时间戳数字,我还没有找到一个,那么strftime/strptime就有一个问题,即它们不对称。
2admgd593#
有两种简单的方法可以做到这一点。
b1zrtrql4#
@Martijn是或可能是在会话变量中保存对象的正确方式。但是这个问题在回到Django 1.5后就解决了。所以这个问题是专门针对Django 1.6.2的。希望这对你有帮助。
pgpifvop5#
Django 1.6或更高版本的对象不能存储在session中。如果你不想改变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
希望对你有帮助!
xpszyzbs6#
--〉永远不想做这样的事情!〈--
使用session和ctypes的Django:请阅读下面的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..."
cbjzeqam7#
在我的例子中,由于对象是不可序列化的(selenium webdriver),我不得不使用全局变量,这非常有效。
7条答案
按热度按时间dvtswwa31#
在会话中,我只存储对象主键:
以及当从会话加载卡时,通过以下方式再次获得卡:
如果会话中没有
card
条目或者特定的卡不存在,则将card
设置为None
。默认情况下,会话数据被序列化为JSON。您也可以提供自己的序列化器,它知道如何存储
card.id
值或其他表示,并在反序列化时再次生成您的Card
示例。gywdnpxw2#
不幸的是,如果对象不是数据库对象,而是其他类型的对象(例如,日期时间或对象类Foo(object)),则建议的答案不起作用:不是数据库模型对象的传递。
当然,如果对象碰巧有一些id字段,你可以将id字段存储在数据库中,并从那里查找值,但通常它可能没有这样一个简单的值,唯一的方法是将数据转换为字符串,这样你就可以读取该字符串,并根据字符串中的信息重建对象。
在datetime对象的情况下,这会变得更加复杂,因为尽管简单的datetime对象可以通过不打印任何内容来打印出格式%Z,但strptime对象无法读取格式%Z(如果没有任何内容),它将阻塞,除非那里有有效时区规范-所以如果你有一个datetime对象,可能包含也可能不包含tzinfo字段,你真的必须做两次strptime,一次用%Z,然后如果它没有%Z就阻塞了。这很愚蠢。更愚蠢的是,datetime对象有一个fromtimestamp函数,但没有一个totimestamp函数,该函数统一产生一个fromtimestamp将读取的时间戳。如果有一个格式代码产生时间戳数字,我还没有找到一个,那么strftime/strptime就有一个问题,即它们不对称。
2admgd593#
有两种简单的方法可以做到这一点。
b1zrtrql4#
@Martijn是或可能是在会话变量中保存对象的正确方式。
但是这个问题在回到Django 1.5后就解决了。所以这个问题是专门针对Django 1.6.2的。
希望这对你有帮助。
pgpifvop5#
Django 1.6或更高版本的对象不能存储在session中。如果你不想改变cookie值的行为,你可以在那里添加一个字典。这可以用于非数据库对象,如类对象等。
希望对你有帮助!
xpszyzbs6#
--〉永远不想做这样的事情!〈--
使用session和ctypes的Django:请阅读下面的Martijn Pieters解释注解。
cbjzeqam7#
在我的例子中,由于对象是不可序列化的(selenium webdriver),我不得不使用全局变量,这非常有效。