juju
juju

Reputation: 994

Using Django to create sessions and buttons connecting Products to a shopping cart through templates and views.py

Sorry for the length (Thought the info was relevant), and thank you for helping understand how this works. I'm trying to use sessions and Django templates to add items to shopping cart. I'm fairly new to learning Django and have painstakingly read through a bunch of documentation and Stack Overflow problems that were similar. My data is saved to MySQL database(subject to change) like this:

sql_entry = {
        'model': 'App.Product',
        'pk': 1, # unique for each item
        'fields': {
                    'Name': 'name',
                    'Price': 1.0,
                    'Quantity': 1
        }

and my Model:

    class Product(models.Model):
    Name = models.CharField(max_length=200, default='')
    Price = models.FloatField()
    Quantity = models.IntegerField()


    def __str__(self):
        return self.Name

    class Meta:
        ordering = ['Name']

Because the actual products will change daily, I want to avoid hardcoding categories, and thought it would be better to only have data pertaining to what products are available. So I use Django's template to create a basic table view of each product with a button that would add it to the cart. I want to avoid any type of login for now. I read that sessions was the best way for unique customers to add items to the cart and save there data to my database. I believe my "add to cart" button needs to temporarily save their entry to my database somehow corresponding with their session ID. This is where I'm having a lot of trouble. In the following blocks of code, I am attempting to add an item to a sessions cart which should be unique to each browser. When I click the button, it redirects to the cart but nothing happens. If you could let me know how bad I have my settings configured that would be awesome. Here are views, cart template, and url patterns:

Sessions settings in views.py

    def index(request):
    response = render_to_response('buylist/Home.html')
    visits = int(request.COOKIES.get('visits', '0'))
    if 'last_visit' in request.COOKIES:
        last_visit = request.COOKIES['last_visit']
        last_visit_time = datetime.strptime(last_visit[:-7], "%Y-%m-%d %H:%M:%S")
        if (datetime.now() - last_visit_time).days > 0:
            response.set_cookie('visits', visits + 1)
            response.set_cookie('last_visit', datetime.now())
    else:
        response.set_cookie('last_visit', datetime.now())
    return response

add to cart function in views.py

# add Product to cart after button click
def add_to_cart(request, product_id):
    cart = request.session.get('cart', {})
    product = Product.objects.get(id=product_id)
    cart[product_id] = product
    request.session['cart'] = cart
    return HttpResponseRedirect(reverse("cart"))


# Cart View
def get_cart(request):
    cart = request.session.get('cart',{})
    return render(request, 'buylist/cart.html', cart)

and here is the template and url patterns I have:

basic.html #Product product page that has button

{% for item in file %}
    <tbody>
      <tr>
        <td>{{item.fields.Name}}</td>
        <td>${{item.fields.Price}}</td>
        <td>{{item.fields.Quantity}}</td>
        <td>
            <a href="http://127.0.0.1:8000/cart/{{item.id}}"><button>Add</button></a>      
        </td>

      </tr>
    </tbody>
{% endfor %}

Url Patterns in App.urls

    path('cart/<int:product_id>/', views.add_to_cart, name='add'),
    path('cart/', views.get_cart, name='cart'),

cart.html

<table>
    <tr>
        <center><h2>Shopping Cart</h2></center>
        <th>Product|</th>
        <th>Quantity|</th>
        <th>Total Price</th>
    </tr>

    {% for item in cart %}
    <tr>
        <td>{{item}}</td>
    </tr>
    {% endfor %}
</table>

Upvotes: 2

Views: 2729

Answers (1)

Ishwar Jangid
Ishwar Jangid

Reputation: 317

To update your cart do it like this. It will remove the product if added and add the product if not present in cart. BOTH FUNCTIONS. The product_id is coming from HTML form given in the end. It is that product which you want to add in your cart.

def cart_update(request):
    p = request.POST.get("product_id")
    if p is not None:
        product_obj = Product.objects.get(id =p)
        c,n = Cart.objects.get_or_new(request)
        if product_obj not in c.products.all():
            c.products.add(product_obj)

    else:
        c.products.remove(product_obj)
        print("to be added")

    return redirect("cart:home")

Cart model is

class Cart(models.Model):
    user = models.ForeignKey(User, null = True, blank = True)
    products = models.ManyToManyField(Product, blank= True)

    subtotal = models.DecimalField(default = 0.00, max_digits= 12, decimal_places=2)

    total = models.DecimalField(default = 0.00, max_digits= 12, decimal_places=2)
    updated = models.DateTimeField(auto_now =True)
    timestamp = models.DateTimeField(auto_now_add  = True)
    objects  = CartManager()

    def __str__(self):
        return str(self.id)

class CartManager(models.Manager):
    def get_or_new(self,request):
        cart_id = request.session.get('cart_id', None)
        qs = self.get_queryset().filter(id = cart_id)
        if qs.count() ==1:
            new_obj = False
            cart_obj = qs.first()
            if request.user.is_authenticated() and cart_obj.user is None:
                cart_obj.user = request.user
                cart_obj.save()
       else:
            new_obj = True
            cart_obj = Cart.objects.new_cart(user = request.user)
            request.session['cart_id'] = cart_obj.id
       return cart_obj, new_obj

Your HTML form

<h1>Your Cart</h1>

{% for a in cart.products.all %}
<form action="{% url "cart:update" %}" method="POST">{% csrf_token %}

<input type="hidden" name="product_id" value='{{a.id}}' placeholder="
 {{a.id}}"/>

<h4>Your Product: <a href= '{{ a.get_absolute_url}}'>{{a.title}}</a><small>
<br><button type="submit">Remove?</button></small></h4>
<p>Price :

{{a.price}}</p>
</form>
{% endfor %}

<b>Subtotal: {{cart.subtotal}}</b><br>

Total: {{cart.total}}

<a href="{% url "cart:checkout" %}"> Checkout</a>

This is all you have to do. Read the code to understand it fully. It is a little trickier one. I have used the manager to make a new cart object if the user is new. Product model is your model in which you can add a lot of different products.

Upvotes: 1

Related Questions