Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError at /en/ Object of type '__proxy__' is not JSON serializable

I'm trying to implement a breadcrumb in my django project. To archieve that, I've created a mixin which is inherited by every view I have. Here is the code:

class BreadcrumbMixin(object):
    index = False
    url_name = None
    verbose_name = None

    def breadcrumbUpdate(self, breadcrumb, new_value):
        for i in range(len(breadcrumb)):
            if breadcrumb[i]['url_name'] == new_value['url_name']:
                breadcrumb = breadcrumb[:i + 1]
        breadcrumb.append(new_value)

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

        new_value = {
            'url_name' : self.url_name,
            'verbose_name' : self.verbose_name,
            'url' : reverse_lazy(self.url_name, **kwargs)
        }

        if self.index:
            self.request.session['breadcrumb'] = [new_value,]
        else:
            self.breadcrumbUpdate(self.request.session['breadcrumb'], new_value)
        return context

The attributes index, url_name and verbose_name are set in each view that inherits it. For instance:

class Index(BreadcrumbMixin, TemplateView):
    template_name = 'crud/index.html'
    index = True
    url_name = 'index' # Name argument used in urls.py
    verbose_name = _('Index')

It basically uses these informations to make a list of dicts, which is passed to the template using the session dictionary. In the template, it is being called like this:

<div style="margin-left: 10px;">
    {% for element in request.session.breadcrumb %}
        <a href="{{ element.url }}" class="breadcrumb"> {{ element.verbose_name }} </a>
    {% endfor %}
</div>

The problem is, it's giving me the error mentioned in the title. Here is the traceback:

Environment:


Request Method: GET
Request URL: http://localhost:8000/en/

Django Version: 2.0
Python Version: 3.6.3
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'crud']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/home/jcarvalho/.envs/webdesk/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  35.             response = get_response(request)

File "/home/jcarvalho/.envs/webdesk/lib/python3.6/site-packages/django/utils/deprecation.py" in __call__
  97.             response = self.process_response(request, response)

File "/home/jcarvalho/.envs/webdesk/lib/python3.6/site-packages/django/contrib/sessions/middleware.py" in process_response
  58.                             request.session.save()

File "/home/jcarvalho/.envs/webdesk/lib/python3.6/site-packages/django/contrib/sessions/backends/signed_cookies.py" in save
  41.         self._session_key = self._get_session_key()

File "/home/jcarvalho/.envs/webdesk/lib/python3.6/site-packages/django/contrib/sessions/backends/signed_cookies.py" in _get_session_key
  77.             serializer=self.serializer,

File "/home/jcarvalho/.envs/webdesk/lib/python3.6/site-packages/django/core/signing.py" in dumps
  109.     data = serializer().dumps(obj)

File "/home/jcarvalho/.envs/webdesk/lib/python3.6/site-packages/django/core/signing.py" in dumps
  87.         return json.dumps(obj, separators=(',', ':')).encode('latin-1')

File "/usr/lib64/python3.6/json/__init__.py" in dumps
  238.         **kw).encode(obj)

File "/usr/lib64/python3.6/json/encoder.py" in encode
  199.         chunks = self.iterencode(o, _one_shot=True)

File "/usr/lib64/python3.6/json/encoder.py" in iterencode
  257.         return _iterencode(o, 0)

File "/usr/lib64/python3.6/json/encoder.py" in default
  180.                         o.__class__.__name__)

Exception Type: TypeError at /en/
Exception Value: Object of type '__proxy__' is not JSON serializable

From what I understood, it's not being able to serialize the breadcrumb to be used in the template, but why?

PS: I've never worked directly with JSON, so I don't know how to deal with it.

like image 513
Jefferson Carvalho Avatar asked Jan 26 '18 01:01

Jefferson Carvalho


1 Answers

When using the JSONSerializer for storing data in the session object, that data must only contain values that can be translated to json.

In your code you are using some lazy objects, that's where you get that __proxy__. Those have to be converted to strings before serializing.

new_value = {
        'url_name' : self.url_name,
        'verbose_name' : str(self.verbose_name),
        'url' : str(reverse_lazy(self.url_name, **kwargs))  # or just reverse()
    }

You can also write your own serializer or use DjangoJSONEncoder (I've not tried that myself, but reading the docs, it seems that that serializer can handle lazy objects.)

like image 125
Håken Lid Avatar answered Nov 08 '22 04:11

Håken Lid