Json Serialization / Form Validation error

1332 views
Skip to first unread message

justin...@gmail.com

unread,
Oct 17, 2008, 4:55:00 PM10/17/08
to Django users
Hello,

I'm having a hard time understanding why Django won't let me serialize
a dictionary of form errors. Can anyone explain why Django throws an
error if I try to serialize someform.errors, even if I copy it into a
plain dictionary?

#!/usr/bin/env python
from django.utils import simplejson
from project.main.models import SampleForm

test = {}
simplejson.dumps(test) # works

test = {'key': [u"value"]}
simplejson.dumps(test) # works

# suppose SampleForms wants a text and url field
# I just give it a text field to test
form = SampleForm({"text": "sample text"})
d = {} # make a new dictionary
# update d so we're working with a plain dictionary
d.update(f.errors)
type(d) # returns dict

# fails: <django.utils.functional.__proxy__ object at 0x00C83810>
# is not JSON serializable
simplejson.dumps(d)

justind

unread,
Oct 18, 2008, 12:58:41 PM10/18/08
to Django users
Hello,

No one has any ideas?

The code I'm actually using in my view is almost identical to the
validage_contact view from
http://toys.jacobian.org/presentations/2007/oscon/tutorial/ (single
slide: http://toys.jacobian.org/presentations/2007/oscon/tutorial/images/django-master-class.081.png)
and I'm using the JsonResponse function from those slides as well.

Has something changed since these were published? Is this a bug?

On Oct 17, 4:55 pm, "justin.don...@gmail.com"

TiNo

unread,
Oct 18, 2008, 4:07:20 PM10/18/08
to django...@googlegroups.com
Could you try this with simplejson not bundled with Django? If that works this is probably a bug in the version bundled with Django.

justind

unread,
Oct 18, 2008, 4:21:11 PM10/18/08
to Django users
I get exactly the same thing.

Here's what I'm entering.

>>> import simplejson
>>> simplejson
<module 'simplejson' from 'C:\Python25\lib\site-packages
\simplejson-2.0.3-py2.5.
egg\simplejson\__init__.pyc'>
>>> from myproject.app.models import MyForm
>>> f = MyForm({'link': 'footext'})
>>> f.errors
{'text': [u'This field is required.'], 'link': [u'Enter a valid
URL.']}
>>> simplejson.dumps(f.errors)

Traceback (most recent call last):
File "<console>", line 1, in <module>
File "build\bdist.win32\egg\simplejson\__init__.py", line 238, in
dumps
File "build\bdist.win32\egg\simplejson\encoder.py", line 198, in
encode
chunks = list(chunks)
File "build\bdist.win32\egg\simplejson\encoder.py", line 421, in
_iterencode
for chunk in _iterencode_dict(o, _current_indent_level):
File "build\bdist.win32\egg\simplejson\encoder.py", line 395, in
_iterencode_d
ict
for chunk in chunks:
File "build\bdist.win32\egg\simplejson\encoder.py", line 318, in
_iterencode_l
ist
for chunk in chunks:
File "build\bdist.win32\egg\simplejson\encoder.py", line 429, in
_iterencode
o = _default(o)
File "build\bdist.win32\egg\simplejson\encoder.py", line 173, in
default
raise TypeError("%r is not JSON serializable" % (o,))
TypeError: <django.utils.functional.__proxy__ object at 0x01182870> is
not JSON
serializable

My test form is just:

class PrecedenceForm(forms.Form):
text = forms.CharField()
link = forms.URLField()

Thanks for looking. Any one have any other ideas?

On Oct 18, 4:07 pm, TiNo <tin...@gmail.com> wrote:
> Could you try this with simplejson not bundled with Django? If that works
> this is probably a bug in the version bundled with Django.
>
> On Sat, Oct 18, 2008 at 6:58 PM, justind <justin.don...@gmail.com> wrote:
>
> > Hello,
>
> > No one has any ideas?
>
> > The code I'm actually using in my view is almost identical to the
> > validage_contact view from
> >http://toys.jacobian.org/presentations/2007/oscon/tutorial/(single
> > slide:
> >http://toys.jacobian.org/presentations/2007/oscon/tutorial/images/dja...
> > )

justind

unread,
Oct 18, 2008, 4:25:45 PM10/18/08
to Django users
Actually the test form is (I forgot to change the name)

class MyForm(forms.Form):
text = forms.CharField()
link = forms.URLField()

Russell Keith-Magee

unread,
Oct 19, 2008, 2:14:20 AM10/19/08
to django...@googlegroups.com
On Sun, Oct 19, 2008 at 12:58 AM, justind <justin...@gmail.com> wrote:
>
> Hello,
>
> No one has any ideas?

Settle down, Tiger. You asked this question on a Friday night. You may
need to wait a little more than 18 hours if you want a response.
We're all volunteers here, and many of us have professional and family
obligations that take priority over answering questions on a mailing
list.

To answer your question - although it may not be immediately obvious
to you _why_ this is occurring, the error message you have received
does tell you exactly _what_ is occurring.

Although form.errors appears to be a dictionary containing strings
(i.e., a dictionay of lists of strings appear when you print
form.errors), it's actually an ErrorDict that contains ValidationError
objects. These, in turn, are manipulated in various ways to ensure
correct unicode output - and one of those manipulations is the use of
proxy objects (django.utils.functional.__proxy__). If you call str()
on a proxy object, it will evaluate and return the underlying string,
but the object itself isn't a string.

SimpleJSON (and the Django copy of the SimpleJSON library) only knows
how to serialized basic Python types, so it complains when you give it
a proxy object. This use of proxy objects in this way was something
introduced by the introduction of full unicode support in Django.
Jacob's slide predate the introduction of feature, which explains why
the example he gave doesn't work out of the box with a more recent
Django version.

However, If you force the rollout of the proxy objects before calling
dumps(), SimpleJSON will correctly encode the form errors. Something
like:

>>> simplejson.dumps(dict((key,str(v) for v in values) for key,values in form.errors.items())

should do the trick.

Yours,
Russ Magee %-)

Rodrigue

unread,
Dec 17, 2008, 4:42:06 AM12/17/08
to Django users
Hi Russell,

I bumped into the same issue today and was glad I found this post.
However, I found that I had to use unicode() rather than str(),
which turns your example into:

content = dict((key, [unicode(v) for v in values]) \
for key, values in
form.errors.items())

With str() the proxy returns '<django.utils.functional.__proxy__
object at 0x83878ac>' (i.e. it only puts the name into quotes)

On Oct 19, 6:14 am, "Russell Keith-Magee" <freakboy3...@gmail.com>
wrote:
> > slide:http://toys.jacobian.org/presentations/2007/oscon/tutorial/images/dja...)

Alex

unread,
Jan 16, 2009, 1:57:49 AM1/16/09
to Django users
I ran into this same problem but the code snippets you guys gave
weren't working. In case anyone is reading this in the future, here is
what you want:

dict([(k, [unicode(e) for e in v]) for k,v in errors.items()])

The above line will give a dictionary of field names mapping to lists
of errors.

HTH

adrian

unread,
Feb 10, 2009, 5:50:37 PM2/10/09
to Django users
Thank you all for posting this. You saved me probably hours of head
scratching.
Message has been deleted

Bro

unread,
Apr 2, 2009, 9:39:52 AM4/2/09
to Django users
But before, is it possible to serialize a form in JSON ?

Thanks
Reply all
Reply to author
Forward
0 new messages