S
S
Stanislav2019-06-26 22:48:11
Django
Stanislav, 2019-06-26 22:48:11

Django session: Object of type is not JSON serializable?

Good evening. Ran into a similar problem with Django session(serialization error) . Created 2 applications under the basket and under the favorites. If I disable 1 of them in settings, then the other one works without errors. Or if you add a product to your favorites and a basket - it works, otherwise I get an error

raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Goods is not JSON serializable

# Ошибка: корзина пустая, 1 товар в избранном
{'1': {}} # print(self.session.get('favorites'))
{} # print(self.session.get('cart'))

Saving and deleting works. The error occurs during the output, I assume that in __iter__
services.py
from apps.goods.models import Goods

class Favorites(object):

  def __init__(self, request):
    """ Initialize the favorites """
    self.session = request.session
    favorites = self.session.get('favorites')

    if not favorites:
      favorites = self.session['favorites'] = {}
    self.favorites = favorites

  def save(self):
    """ 
    Mark the session as "modified" to make sure it gets saved
    """
    # добавил строку из решения по ссылке но не помогло
    # self.session['favorites'] = self.favorites = self.session.get('favorites', []) 
    
    self.session.modified = True

  def add(self, goods):
    """
    Add a goods to the favorite
    """
    goods_id = str(goods.id)
    if goods_id not in self.favorites:
      self.favorites[goods_id] = {}
    self.save()

  def remove(self, goods):
    """
    Remove a goods from the favorite
    """
    goods_id = str(goods.id)
    if goods_id in self.favorites:
      del self.favorites[goods_id]
      self.save()                          

  def __iter__(self):
    """
    Iterate over the items in the favorites and get the goods 
    from the database.
    """
    goods_ids = self.favorites.keys()    
    products = Goods.objects.filter(id__in=goods_ids)
    favorites = self.favorites.copy()
    for product in products:
      favorites[str(product.id)]['goods'] = product        
  
    for item in favorites.values():
        yield item

  def __len__(self):
    return len(self.favorites)

views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.views.decorators.http import require_POST
from apps.goods.models import Goods
from .services import Favorites

def favorites(request):
  favorites = Favorites(request)
  return render(request, 'wishlist/favorites.html', {'favorites': favorites})

def add_favorites(request, goods_id):
  favorites = Favorites(request)
  goods = get_object_or_404(Goods, id=goods_id)
  favorites.add(goods = goods)
  return redirect('favorites')

def remove_favorites(request, goods_id):
  favorites = Favorites(request)
  goods = get_object_or_404(Goods, id=goods_id)
  favorites.remove(goods)
  return redirect('favorites')

In services for the basket is similar, but with the addition of additional data
apps.cart.services

from decimal import Decimal
from apps.goods.models import Goods


class Cart(object):

  def __init__(self, request):
    """ Initialize the cart. """
    self.session = request.session
    cart = self.session.get('cart')
    if not cart:
        # save an empty cart in the session
        cart = self.session['cart'] = {}
    self.cart = cart


  def add(self, goods, size, quantity=1, update_quantity=False):
      """
      Add a goods to the cart or update its quantity.
      """
      goods_id = str(goods.id) + size
      if goods_id not in self.cart:
          self.cart[goods_id] = {'id': str(goods.id),
                                 'quantity': 0, 
                                 'price': goods.price,
                                 'size': size}
      if update_quantity:
          self.cart[goods_id]['quantity'] = quantity
      else:
          self.cart[goods_id]['quantity'] += quantity
      self.save()


  def save(self):
    """ 
    Mark the session as "modified" to make sure it gets saved
    """
    # строка из решения по ссылке не помогло
    # self.session['cart'] = self.cart = self.session.get('cart', [])
    self.session.modified = True


  def remove(self, goods, size):
    """
    Remove a goods from the cart
    """
    goods_id = str(goods.id) + size
    if goods_id in self.cart:
      del self.cart[goods_id]
      self.save()
  

  def __iter__(self):
    """
    Iterate over the items in the cart and get the goods 
    from the database.
    """
    goods_ids = list()
    for key in self.cart.values():
      goods_ids.append(key['id'])

    # get the product objects and add them to the cart
    products = Goods.objects.filter(id__in=goods_ids)
    cart = self.cart.copy()
    for product in products:
        for el in self.cart.values():
          id = str(product.id)
          if el['id'] == id:
            cart[ id + el['size'] ]['goods'] = product
            self.cart[ id + el['size'] ]['price'] = product.price
  
    for item in cart.values():
        item['total_price'] = item['price'] * item['quantity']
        yield item
  

  def __len__(self):
    """
    Count all items in the cart.
    """
    return sum(item['quantity'] for item in self.cart.values())


  def get_total_price(self):
    return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())


  def clear(self):
    """
    Remove cart from session
    """ 
    del self.session['cart']
    self.save()


I don't understand why there is a conflict?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
R
Roman Kitaev, 2019-06-26
@Chebaa

You add an ORM model object to the session. The JSON session is serialized. Model object not serializing to JSON (out of the blue)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question