Reputation: 2645
I have a simple view
def foo(request):
card = Card.objects.latest(datetime)
request.session['card']=card
For the above code I get the error
"<Card: Card object> is not JSON serializable"
Django version 1.6.2. What am I doing wrong ?
Upvotes: 19
Views: 24868
Reputation: 41
Unfortunately the suggested answer does not work if the object is not a database object but some other kind of object - say, datetime
or an object class Foo(object): pass
that isn't a database model object.
Sure, if the object happen to have some id field you can store the id field in the database and look up the value from there but in general it may not have such a simple value and the only way is to convert the data to string in such a way that you can read that string and reconstruct the object based on the information in the string.
In the case of a datetime
object this is made more complicated by the fact that while a naive datetime
object can print out format %Z
by simply not printing anything, the strptime
object cannot read format %Z
if there is nothing, it will choke unless there is a valid timezone specification there - so if you have a datetime
object that may or may not contain a tzinfo
field you really have to do strptime
twice once with %Z
and then if it chokes without the %Z
. This is silly. It is made even sillier by the fact that datetime
objects have a fromtimestamp
function but no totimestamp
function that uniformly produces a timestamp that fromtimestamp
will read. If there is a format code that produces timestamp number I haven't found one and again, strftime
/strptime
suffer from the fact that they are not symmetric as described above.
Upvotes: 4
Reputation: 600
In my case, as the object is not serializable (selenium webdriver), I had to use global variables, which is working great.
Upvotes: 0
Reputation: 14742
--> DON'T EVER FEEL LIKE DOING SOMETHING LIKE THIS! <--
Django using session and ctypes: Plz read Martijn Pieters explanation comment below.
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..."
Upvotes: 0
Reputation: 1121514
In a session, I'd just store the object primary key:
request.session['card'] = card.id
and when loading the card from the session, obtain the card again with:
try:
card = Card.objects.get(id=request.session['card'])
except (KeyError, Card.DoesNotExist):
card = None
which will set card
to None
if there isn't a card
entry in the session or the specific card doesn't exist.
By default, session data is serialised to JSON. You could also provide your own serializer, which knows how to store the card.id
value or some other representation and, on deserialization, produce your Card
instance again.
Upvotes: 24
Reputation: 47
Objects cannot be stored in session from Django 1.6 or above. If you don't want to change the behavior of the cookie value(of a object), you can add a dictionary there. This can be used for non database objects like class object etc.
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
Hope it will help you!
Upvotes: 0
Reputation: 847
There are two simple ways to do this.
Upvotes: 3
Reputation: 2645
@Martijn is or might be the correct way to save the object in session variables.
But the issue was solved by moving back to Django 1.5. So this issue is specifically for django 1.6.2.
Hope this helps.
Upvotes: 0