Search code examples
ajaxdjangodjango-sessions

remove item from django-carton with Ajax


This is driving me crazy. I am building an ecommerce app, with the cart in Django-carton. When I add an item to the cart, I can get the item's id from the context into the store, and pass it into my Ajax call and to the view when a customer adds the item with a button click.

I want the customer to be able to delete and edit quantities in the cart using a button, and am now trying to create my delete and my edit quantity functions. I'm stuck because I don't understand how to pass the id the the view in Ajax. The id isn't in the item context object. I can get the id in the view by printing ids = request.session['CART'], but it does not have the current id. The items in context are limited to the following:

self.product = product
self.quantity = int(quantity)
self.price = Decimal(str(price))

The example in Django-carton's documentation has this example, which doesn't use Javascript:

views:

def remove(request):
    cart = Cart(request.session)
    product = Product.objects.get(id=request.GET.get('id'))
    cart.remove(product)
    return HttpResponse("Removed")

urls:

u`rl(r'^remove/$', 'remove', name='shopping-cart-remove'),`

In my view, I can get the ids of all of the objects in the cart with

cart = Cart(request.session)
ids = request.session['CART']

which gives me the following object:

{u'meal_pk': 15, u'price': u'5', u'quantity': 39}

But this doesn't actually seem helpful. This is my first encounter with sessions. I've been reading through the code here https://github.com/lazybird/django-carton/blob/master/carton/cart.py How can I edit or delete an item in my cart?


Solution

  • You can still call the remove view via AJAX quite easily with Javascript; unless otherwise specified, the view does not care if the request is submitted via AJAX. So, we can set that up easily w/ JQuery.

    So, in a template showing the shopping cart, for example:

    {% load carton_tags %}
    {% get_cart as cart %}
    
    <script type="text/javascript" src="path/to/jquery.js">/script>
    
    {% for item in cart.items %}
        <a onclick='AjaxRemove("{% url 'shopping-cart-remove' %}?id={{ item.product.id }}")'>Remove this item</a>
    {% endfor %}
    
    <script type="text/javascript">
        function AjaxRemove(remove_url) {
            $.ajax({
                url: remove_url,
                success: function(response) {alert(response);},
                error: function() {alert("Couldn't remove item");}  
            })
    </script>
    

    will remove the item and give an alert if the AJAX request responds with success.

    You can further customize the view response to respond differently to AJAX requests using request.is_ajax():

    def remove(request):
        cart = Cart(request.session)
        product = Product.objects.get(id=request.GET.get('id'))
        cart.remove(product)
        if request.is_ajax():
            # do something, respond differently
            return HttpResponse("Removed (via AJAX)")
        return HttpResponseRedirect(reverse('shopping-cart-show'))