Reputation: 53
I am creating a web application that will serve as a grocery store. The way I set it up is so the customer can come onto the website, click on the items that they would like to purchase, and then click a submit button to purchase those items. The problem I am running into is having a views.py function to take the information of which products were selected and subtracting 1 from the quantity of the database.
"""models.py"""
class Post(models.Model):
title = models.CharField(max_length=100)
Price = models.DecimalField(max_digits=4, decimal_places=2,default=1)
Sale = models.DecimalField(max_digits=4, decimal_places=2,default=1)
quantity = models.IntegerField(default=1)
author = models.ForeignKey(User, on_delete=models.CASCADE)
category = TreeForeignKey('Category',null=True,blank=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
views.py
class PostListView(ListView):
model = Post
template_name = 'blog/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
def inventory(request):
products = request.POST.getlist('products')
for product in products:
a = Post.objects.get(title=product)
a.quantity = a.quantity -1
a.save()
print(products) # This line isn't necessary but it will show what is in your list from the terminal.
return redirect('blog-home')
urls.py
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
path('inventory', views.inventory, name='inventory'),
home.html
{% extends "blog/base.html" %}
{% block content %}
<form action="{% url 'inventory' %}" method="POST" id="menuForm">
{% for post in posts %}
{% if post.quantity > 0 %}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2">{{ post.category }}</a>
</div>
<h2><a class="article-title" >{{ post.title }}</a></h2>
<p class="article-content"> Price: ${{ post.Price }}</p>
<p class="article-content"> Sale: ${{ post.Sale }}</p>
<input type="checkbox" id="product_{{ post.id }}" value="{{ post.title }}" form="menuForm" name="products" > Inventory count: {{ post.quantity }}
</input>
</div>
</article>
{% else %}
{% endif %}
{% endfor %}
<button type="submit" form="menuForm">Confirm Purchase</button>
</form>
{% endblock content %}
My goal is to click on the checkboxes, and when the customer clicks the button on the bottom of home.html, it triggers the inventory function to subtract "1" from the quantity. When I say print(products), then the terminal gives me the title of all the posts that are check-marked. However, it still isn't going into the database and subtracting 1 from the inventory. (I solved it)
Upvotes: 1
Views: 612
Reputation: 476557
Using Post.objects.get('products[x]')
does not make sence, the .get(…)
method [Django-doc] expects Q
objects as positional parameters, or named parameters, so for example:
from django.shortcuts import redirect
def inventory(request):
products = request.POST.getlist('products')
Post.objects.filter(pk__in=products).update(
quantity=F('quantity')-1
)
return redirect('profile')
By using a .update(…)
[Django-doc] you decrement all Post
s in bulk which is more efficient than making two database queries per Post object.
Using HttpResponseRedirect("{% url 'profile'%}")
will not work either. The "{% url 'profile'%}"
is just a string, it does not perform any template rendering. Django will normally return a HTTP 302 response, with {% url 'profile' %}
as link to go to, but the browser does not understand {% url 'profile' %}
, it can only work with a URI.
Upvotes: 1