18. Add and remove products on cart

Now we will implement the functionality to add and remove products from our cart.

Adding a product

We will modify the add_to_cart function inside views.py to enable the addition of a product via the HTML form. The results are explained below:

views.py
if request.user.is_authenticated:
            client = request.user.client
        else :
            return redirect('store')
        order, created = Order.objects.get_or_create(client=client, finished=False)
        item_stock = ItemStock.objects.get(product__id=product_id, size=size, color=color_id) #? In the forms we enter the color, id, and the size
        item_ordered, created = OrderedItem.objects.get_or_create(order=order, itemstock=item_stock) #? adding the product to the cart
        item_ordered.quantity += 1
        item_ordered.save() #? Must save changes made directly to a element
  1. User Authentication Check: The code first verifies if the user is authenticated. If not, it redirects the user to the store page.

  2. Retrieve or Create Order: If the user is authenticated, it retrieves the client's current order that is not finished. If no such order exists, a new one is created.

  3. Fetch ItemStock: The specific item to be added is fetched from the ItemStock table using the provided product ID, size, and color (those specific parameters were used as they are also the ones being used on the form).

  4. Add or Update OrderedItem: It then adds this item to the order by either updating an existing OrderedItem or creating a new one.

  5. Increment Quantity: The quantity of the item in the order is incremented, and the changes are saved to the database (as changes made directly to the element of a class must be saved).

Modifying product quantity

Currently, we can only add one product at a time to the cart. To change this, we will add plus and minus buttons alongside the displayed quantity on the forms, allowing the user to choose the number of each product they want to add to the car

We will update the cart.html file by integrating buttons using the <form> tag. This approach is consistent with the methodology previously applied to implement the "add to cart" button.

cart.html
<img src="{{ item.itemstock.product.image.url }}" width = "60" height = "80">
    Product: {{ item.itemstock.product.name }}; 
    Color: {{ item.itemstock.color.name }}; 
    Size: {{ item.itemstock.size }}; 
    
    <div style="display:flex;"> <!--Makes eveyrything in the same line-->
        Quantity: 
        <!--! REMOVE BUTTON -->
        <form method = "POST" action = "{% url 'remove_from_cart' item.itemstock.product.id %}"> <!--? Changed the product reference to the one being used in the code above-->
            {% csrf_token %} <!--Protects (by generating a unique token) the forms from hackers trying to replicate it-->
            <input type="hidden" name="size" value="{{ item.itemstock.size }}">
        <input type="hidden" name="color" value="{{ item.itemstock.color.id }}">
        <button type="submit">-</button> 
        </form>

        {{ item.quantity}}
        <!--! ADD BUTTON -->
        <form method = "POST" action = "{% url 'add_to_cart' item.itemstock.product.id %}"> <!--? Changed the product reference to the one being used in the code above-->
            {% csrf_token %} <!--Protects (by generating a unique token) the forms from hackers trying to replicate it-->
        <input type="hidden" name="size" value="{{ item.itemstock.size }}">
        <input type="hidden" name="color" value="{{ item.itemstock.color.id }}">
        <button type="submit">+</button> 
        </form>;
    </div>
    Unit Price: {{ item.itemstock.product.price }}; 
    Total Price: R${{ item.total_price }}
</p>
<hr> <!--Horizonal row-->

The modifications include the following:

  1. Encapsulated Button Code: All button-related code is now enclosed within a <div> tag with a display: flex style. This layout ensures that the buttons appear adjacent to the quantity amount, enhancing the user interface. Further aesthetic improvements will be addressed later in the project.

  2. Action Attributes: Incorporated the remove_from_cart and add_to_cart URLs into the respective action attributes of the <form> elements.

  3. Button Elements: Added the buttons using the <button> tag.

  4. Visual Separation: Included a horizontal line using the <hr> tag to provide visual separation within the page.

In the views.py file, we will create a remove_from_cart function. To achieve this, we will copy the code from the add_to_cart function and make the necessary adaptations.

views.py
def remove_from_cart(request, product_id) :
    if request.method == "POST" and product_id : #? if the user is sending a new product
        data = request.POST.dict() #? converts the request data to a dictionary
        size = data.get('size') #? used get instead of ['size] as it wont return a error
        color_id = data.get('color')
        if not size:
            return redirect('store')
        #!getting the client
        if request.user.is_authenticated:
            client = request.user.client
        else :
            return redirect('store')
        order, created = Order.objects.get_or_create(client=client, finished=False)
        item_stock = ItemStock.objects.get(product__id=product_id, size=size, color=color_id) #? In the forms we enter the color, id, and the size
        item_ordered, created = OrderedItem.objects.get_or_create(order=order, itemstock=item_stock) #? adding the product to the cart
        item_ordered.quantity -= 1 #? only difference is that we are removing a item from the cart
        item_ordered.save() #? Must save changes made directly to a element
        if item_ordered.quantity <= 0 :
            item_ordered.delete()
        return redirect('cart')
    else :
        return redirect('store') #? redirect the user to the store if he didn't choose a product

The adaptations made include:

  1. Quantity Adjustment: Modified the operation from += 1 to -= 1 for item_ordered.quantity to reflect the removal of an item.

  2. Conditional Removal: Added an if condition to check if item_ordered.quantity is less than or equal to 0. If true, the item is removed from the cart list entirely.

Finally, we will add the new remove_from_cart URL to the list of URLs in the urls.py file to ensure proper routing of the remove-from-cart functionality.

urls.py
    path('removefromcart/<int:product_id>/', remove_from_cart, name="remove_from_cart"),

Upon running the site, users can now effectively add and remove items from the cart using the buttons. The cart data, including the total price, dynamically updates to reflect these changes in real-time.

Last updated