title: Django Carton App - Getting Ajax Working
body: <p>I am using the Django Carton shopping cart add on and have got it working. I am now trying to add to cart via an ajax call and struggling to get the code working. I get an error which says "TypeError at /api/cart/↵Object of type 'property' is not JSON serializable" (on the Chrome Console).</p>
  
  <p>Views.py</p>
  
  <pre><code>class ProductListView(ListView):
  (redacted for clarity)
  
  def add(request):
      cart = Cart(request.session)
      product = Product.objects.get(id=request.POST.get('id'))
      cart.add(product, price=product.price)
      added = True
      if request.is_ajax():
          print("Ajax request")
      json_data = {
          "added": added,
      }
      return JsonResponse(json_data)
      return redirect('list')
  
  def remove(request):
      cart = Cart(request.session)
      product = Product.objects.get(id=request.GET.POST('id'))
      cart.remove_single(product)
      return redirect('list')
  
  def show(request):
      return render(request, 'carts/carts.html')
  
  def cart_detail_api_view(request):
      # cart_obj, new_obj = Cart.objects.new_or_get(request)
      cart = Cart(request.session)
      products = [{"name": x.name, "price": x.price} for x in cart.products.all()]
      cart_data = {"products": products, "total": Cart.total}
      return JsonResponse(cart_data)
  </code></pre>
  
  <p>HTML Template:</p>
  
  <pre><code>        {% for product in cat_appetizers %}
          &lt;form method="POST" class='form-product-ajax' action='{% url "shopping-cart-add" %}' data-endpoint='{% url "shopping-cart-add" %}'&gt;
              {% csrf_token %}
              {{ product.name }}
              &lt;input type="hidden" name='id' value='{{ product.id }}'&gt;
              &lt;br/&gt;
              &lt;span class='submit-span'&gt;
              &lt;button&gt;Add to Basket&lt;/button&gt;
              &lt;/span&gt;
          &lt;/form&gt;
          &lt;br/&gt;
      {% endfor %}
          {% load carton_tags %}
          {% get_cart as cart %}
      &lt;div&gt;
          &lt;h4&gt;This is your shopping cart&lt;/h4&gt;
          &lt;table class="cart-table"&gt;
              &lt;tbody class="cart-body"&gt;
                  &lt;tr&gt;These are the items in your basket and their respective totals&lt;/tr&gt;&lt;br&gt;
                  {% for item in cart.items %}
                  &lt;form method="GET" action='{% url "shopping-cart-remove" %}'&gt;    
                  &lt;tr&gt;{{ item.quantity }} x {{ item.product.name }} = {{ item.subtotal }}&lt;/tr&gt;
                  &lt;input type="hidden" name='id' value='{{ item.product.id }}'&gt;
                  &lt;button&gt;remove&lt;/button&gt;&lt;br&gt;
                  &lt;/form&gt;
          {% endfor %}
              &lt;/tbody&gt;
              &lt;tr class="cart-total-sec"&gt;&lt;td class="cart-price"&gt;{{ cart.total }}&lt;/td&gt;&lt;/tr&gt;
      &lt;/div&gt;
  </code></pre>
  
  <p>Jquery/Ajax:</p>
  
  <pre><code> $(document).ready(function() {
       var productForm = $(".form-product-ajax") // #form-product-ajax
       productForm.submit(function(event) {
           event.preventDefault();
           console.log("Form is not sending")
           var thisForm = $(this)
               //var actionEndpoint = thisForm.attr("action");
           var actionEndpoint = thisForm.attr("data-endpoint");
           var httpMethod = thisForm.attr("method");
           var formData = thisForm.serialize();
           $.ajax({
               url: actionEndpoint,
               method: httpMethod,
               data: formData,
               success: function(data) {
                   var submitSpan = thisForm.find(".submit-span")
                   if (data.added) {
                       submitSpan.html("In cart &lt;button type='submit' class='btn btn-link'&gt;ADD TO BASKET&lt;/button&gt;")
                   }
                   var currentPath = window.location.href
                   if (currentPath.indexOf("") != -1) {
                       refreshCart()
                   }
               },
               error: function(errorData) {
                   console.log("error")
                   console.log(errorData)
               }
           })
  
           function refreshCart() {
               console.log("in current cart")
               var cartTable = $(".cart-table")
               var cartBody = cartTable.find(".cart-body")
                   // $(cartBody).empty()
               var productRows = cartBody.find(".cart-product")
               var cartTotal = cartTable.find(".cart-total-sec")
               var currentUrl = window.location.href
               var refreshCartUrl = '/api/cart/'
               var refreshCartMethod = "GET";
               var data = {};
               $.ajax({
                   url: refreshCartUrl,
                   method: refreshCartMethod,
                   data: data,
                   success: function(data) {
                       console.log("success")
                       console.log(data)
  
                       if (data.products.length &gt; 1) {
                           $(cartBody).empty()
                           productRows.html("")
                           $.each(data.products, function(index, value) {
                               console.log(value)
                               console.log(data.count)
  
                               cartBody.append("&lt;tr&gt;&lt;td&gt;" + value.name + "&lt;/td&gt;&lt;td&gt;" + value.price + "&lt;/td&gt;&lt;/tr&gt;")
                           })
                           cartTotal.find(".cart-total").text(data.total)
  
                           console.log(data.total)
  
                       } else {
                           window.location.href = currentUrl
                       }
                   },
                   error: function(errorData) {
                       console.log("error")
                       console.log(errorData)
                   }
               })
           }
  
       })
   })
  </code></pre>