如何将django对象存储为会话变量(对象不是JSON可序列化的)?

时间:2014-03-10 07:57:03

标签: python django

我有一个简单的视图

def foo(request):
   card = Card.objects.latest(datetime)
   request.session['card']=card

对于上面的代码,我收到了错误

"<Card: Card object> is not JSON serializable"

Django版本1.6.2。我究竟做错了什么 ?

6 个答案:

答案 0 :(得分:13)

在cookie中,我只存储对象主键:

request.session['card'] = card.id

当从会话中加载卡时,请使用以下方法再次获取卡:

try:
    card = Card.objects.get(id=request.session['card'])
except (KeyError, Card.DoesNotExist):
    card = None
如果会话中没有card条目或特定卡不存在,

会将None设置为card

答案 1 :(得分:3)

有两种简单的方法可以做到这一点。

  • 如果每个对象同时属于一个会话,则将会话ID存储为模型字段,并更新模型。
  • 如果一个对象可以同时属于多个会话,则将object.id存储为会话变量。

答案 2 :(得分:2)

不幸的是,如果对象不是数据库对象,而是某些其他类型的对象(例如,datetime或对象类Foo(对象)),则建议的答案不起作用:传递不是数据库模型对象。

当然,如果对象碰巧有一些id字段,你可以将id字段存储在数据库中并从那里查找值,但一般情况下它可能没有这么简单的值,唯一的方法是转换数据以这样的方式字符串,你可以读取该字符串并根据字符串中的信息重建对象。

在日期时间对象的情况下,由于一个天真的日期时间对象可以通过简单地不打印任何东西来打印出格式%Z,因此strptime对象无法读取格式%Z,如果没有任何内容,它会变得更加复杂。除非有一个有效的时区规范,否则会阻塞 - 所以如果你有一个可能包含或不包含tzinfo字段的日期时间对象,你必须使用%Z进行两次strptime然后如果它没有%Z就会窒息。这太傻了。由于datetime对象具有fromtimestamp函数但没有totimestamp函数可以统一生成fromtimestamp将读取的时间戳,因此它更加愚蠢。如果有一个生成时间戳编号的格式代码,我还没有找到,strftime / strptime会受到如上所述它们不对称的事实的影响。

答案 3 :(得分:2)

在Django中,您可以使用会话 ctypes 执行以下操作:

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..."

答案 4 :(得分:1)

@Martijn是或者可能是在会话变量中保存对象的正确方法。

但问题是通过回到Django 1.5来解决的。所以这个问题专门针对django 1.6.2。

希望这会有所帮助。

答案 5 :(得分:0)

无法将对象存储在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 

希望它将对您有帮助!