1

I have to store some data in the window object to use it un the frontend rendering. I have a model:

from django.db import models
from tools.various.db import Base
from tools.files.fields import CustomImgField, IMAGES_DIRECTORY_ORIGINAL
from django.conf import settings

class myModel(Base):
    myName                     = models.CharField(max_length=100, verbose_name='myName')
    mySurname                  = models.CharField(max_length=100, verbose_name='mySurname')

I have a view:

from django.http import Http404
from django.views.generic import TemplateView
from django.http import JsonResponse
from json import dumps
from front.models import Language
from front.models import myModel


class BaseView(TemplateView):
    def get_context_data(self, **kwargs):
        context = super(BaseView, self).get_context_data(**kwargs)

        context['myData'] = myModel.objects.value()
        return context

And I want to retrieve myData as a JSON object and store it in window object:

  window.app = {
    data: {},
    settings: {
      staticUrl: '{{ STATIC_URL }}',
      urls: {},
      storedData: {{ myData|jsonify|safe }}
    }
  };

But I get this response:

[{'myName': u'foo', 'mySurname': u'bar', u'id': 1L, 'order': 0L}] is not JSON serializable

Does anyone knows what I'm doing wrong?

Thanks!

EDIT:

I just tried return list(context) as André Laszlo proposes: it returns

Exception Value: list indices must be integers, not str

But if I use:

    context['myData'] = list(myModel.objects.values())
    return context

It seems to work. I'm going to read the documentation about 'list()'.

  • What does `myModel.objects.value()` return? Do you have an `Order` model? –  Nov 11 '17 at 19:07
  • Hi Blurp, with `myModel.objects.value()` I get the same result, `[{'myName': u'foo', 'mySurname': u'bar', u'id': 1L, 'order': 0L}] is not JSON serializable` –  Nov 11 '17 at 19:08
  • Can you show the `value()` method? –  Nov 11 '17 at 19:11
  • Possible duplicate of [ is not JSON serializable](https://stackoverflow.com/questions/16790375/django-object-is-not-json-serializable) –  Nov 11 '17 at 19:12
  • Sorry, it is `values()`, not `value()`: `myModel.objects.values()` –  Nov 11 '17 at 19:13
  • Possible duplicate of [is not JSON serializable](https://stackoverflow.com/questions/16336271/is-not-json-serializable) – André Laszlo Nov 11 '17 at 19:14
  • Yes, I have been reading those stackoverflow posts, but no results –  Nov 11 '17 at 19:15
  • What's this `jsonify` filter you're using? –  Nov 11 '17 at 19:21
  • `.values()` returns a `QuerySet` and it looks like your `jsonify` filter can't handle that. You might need to convert the value returned from `myModel.objects.values()` to a list first. –  Nov 11 '17 at 19:30

2 Answers2

2

I think that the problem is that your list is actually not a list, it's a QuerySet that just looks like a list when printed.

Have you tried:

context['myData'] = list(myModel.objects.values())
return context

I think it should return a list with dictionaries, which should be JSON serializeable. Please update your question with your results if it doesn't work.

André Laszlo
  • 13,970
  • 2
  • 60
  • 73
2

You are returning a python dictionary, you need to serialize it to JSON using json.dumps()

You are already importing json but not making use of it.

from django.http import Http404
from django.views.generic import TemplateView
from django.http import JsonResponse
from json import dumps
from front.models import Language
from front.models import myModel

class BaseView(TemplateView):
    def get_context_data(self, **kwargs):
        context = super(BaseView, self).get_context_data(**kwargs)
        context['myData'] = myModel.objects.value()
        return dumps(context)

Additionally, you might want to read up on ujson - Faster than the builtin json library.

Preferably, if you are using Django 1.7+ you can do:

from django.http import Http404
from django.views.generic import TemplateView
from django.http import JsonResponse
from json import dumps
from front.models import Language
from front.models import myModel
from django.http import JsonResponse


class BaseView(TemplateView):
    def get_context_data(self, **kwargs):
        context = super(BaseView, self).get_context_data(**kwargs)

        context['myData'] = myModel.objects.value()
        return JsonResponse(context)
alexisdevarennes
  • 4,602
  • 3
  • 21
  • 37
  • Thank you alexis; with `context['myData'] = list(myModel.objects.values())` it works; it is better to use json.dumps()? –  Nov 11 '17 at 19:42
  • Well, it's odd that it works by doing it that way. Try my approach, if it works that way, use it. Using JsonResponse from django.http is the best approach. – alexisdevarennes Nov 11 '17 at 19:44
  • Also because by using that, it sets the correct response headers, content-type: application/json for you. You can read about it here: https://docs.djangoproject.com/en/1.11/ref/request-response/#jsonresponse-objects – alexisdevarennes Nov 11 '17 at 19:45
  • But, what if I have different contexts in my view, and I don't want to encode all of them? I imagine that if you apply `return JsonResponse (context)`you are encoding all of them. –  Nov 11 '17 at 19:47
  • You could then do ``return JsonResponse(context["ContextKey"])`` – alexisdevarennes Nov 11 '17 at 19:48
  • Not sure what you mean. But JSON serialization is quite fast, specially using ``ujson`` – alexisdevarennes Nov 11 '17 at 19:49
  • If you mean, you'd only like to encode ``dictionaries`` you could do: ``if isinstance(context,dict): return JsonResponse(context)`` – alexisdevarennes Nov 11 '17 at 19:50
  • `JsonResponse` doesn't make sense for this scenario. The question shows a template being rendered with a bit of JSON used to initialize the JavaScript on the page. –  Nov 11 '17 at 20:08
  • @NikitaSöze Please mark my answer as correct if it worked for you. – alexisdevarennes Nov 15 '17 at 01:21