Reputation: 1
i created a cart app inside an ecommerce site am building but when i click on the add cart form that is rendered on my page, it doesn't come through. any help will be appreciated
inside the cart app, i have the normal django files in it.(__init__.py
,
admin.py
, apps.py
, cart.py
(added by me), models.py
, tests.py
, urls.py
and views.py
)
Here are the content of files in my cart app that i filled with content. for cart.py:
from cart.models import CartItems
from catalog.models import Product
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect
import decimal
import random
CART_ID_SESSION_KEY = 'cart_id'
# get the current user's cart id, sets new one if blank
def _cart_id(request):
if request.session.get(CART_ID_SESSION_KEY,'') == '':
request.session[CART_ID_SESSION_KEY] = _generate_cart_id()
return request.session[CART_ID_SESSION_KEY]
def _generate_cart_id():
cart_id = ''
characters =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()'
cart_id_length = 50
for y in range(cart_id_length):
cart_id += characters[random.randint(0, len(characters)-1)]
return cart_id
# return all items from the current user's cart
def get_cart_items(request):
return CartItems.objects.filter(cart_id=_cart_id(request))
# add an item to the cart
def add_to_cart(request):
postdata = request.POST.copy()
# get product slug from post data, return blank if empty
product_slug = postdata.get('self.slug','')
# get quantity added, return 1 if empty
quantity = postdata.get('quantity',1)
# fetch the product or return a missing page error
p = get_object_or_404(Product, slug=product_slug)
#get products in cart
cart_products = get_cart_items(request)
product_in_cart = False
# check to see if item is already in cart
for cart_item in cart_products:
if cart_item.product.id == p.id:
# update the quantity if found
cart_item.augment_quantity(quantity)
product_in_cart = True
if not product_in_cart:
# create and save a new cart item
ci = CartItems()
ci.product = p
ci.quantity = quantity
ci.cart_id = _cart_id(request)
ci.save()
# returns the total number of items in the user's cart
def cart_distinct_item_count(request):
return get_cart_items(request).count()
models.py:
from django.db import models
from catalog.models import Product
class CartItems(models.Model):
cart_id = models.CharField(max_length=50)
date_added = models.DateTimeField(auto_now_add=True)
quantity = models.IntegerField(default=1)
product = models.ForeignKey(Product, unique=False,
on_delete=models.CASCADE)
class Meta:
db_table = 'cart_items'
ordering = ['date_added']
def total(self):
return self.quantity * self.product.price
def name(self):
return self.product.name
def price(self):
return self.product.price
def get_absolute_url(self):
return self.product.get_absolute_url
urls.py:
from django.urls import path
from cart import views
urlpatterns = [
path('', views.show_cart, name='show_cart')
]
views.py:
from django.shortcuts import render
from django.template import RequestContext
from cart import cart
def show_cart(request):
cart_item_count = cart.get_cart_items(request)
context_instance = RequestContext(request)
page_title = "showing Cart"
context = {'page_title' : page_title,
'cart_item_count': cart_item_count,
'context_instance': context_instance
}
template = 'cart/cart.html'
return render(request, template, context)
Below are the models.py, views.py and forms.py of another app(catalog) in the project that have inheritance of the cart app
models.py:
from django.db import models
from django.urls import reverse
class Category(models.Model):
name = models.CharField(max_length=50, db_index=True)
slug = models.SlugField(max_length=50, unique=True, help_text="Unique
value for product page URL, created from name.")
description = models.TextField(blank=False)
is_active = models.BooleanField(default=True)
meta_keywords = models.CharField("Meta Keywords", max_length=255,
help_text="Comma-delimited set of SEO keywords for meta tag")
meta_description = models.CharField("Meta Description", max_length=255,
help_text="Content for description meta tag")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = "category"
ordering = ["-created_at"]
verbose_name_plural = "Categories"
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('catalog:show_category', args=[self.slug])
class Product(models.Model):
name = models.CharField(max_length=255, unique=True)
slug = models.SlugField(max_length=255, unique=True, help_text="Unique
value for product page URL, created from name.")
brand = models.CharField(max_length=50)
sku = models.CharField(max_length=50)
price = models.DecimalField(max_digits=9, decimal_places=2)
old_price = models.DecimalField(max_digits=9, decimal_places=2,
blank=True, default=0.00)
image = models.ImageField(upload_to='media', blank=True)
is_active = models.BooleanField(default=True)
is_bestseller = models.BooleanField(default=False)
is_featured = models.BooleanField(default=False)
quantity = models.IntegerField()
description = models.TextField(blank=False)
meta_keywords = models.CharField(max_length=255, help_text = 'Comma-
delimited set of SEO keywords for meta tag')
meta_description = models.CharField(max_length=255, help_text = 'Content
for description meta tag')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
categories = models.ManyToManyField(Category)
class Meta:
db_table = 'products'
ordering = ['-created_at']
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('catalog:show_product', args=[self.slug])
def sale_price(self):
if self.old_price > self.price:
return self.price
else:
return None
views.py:
from django.shortcuts import render, get_object_or_404, redirect
from catalog.models import Category, Product
from django.template import RequestContext
from django.urls import reverse
from cart import cart
from django.http import HttpResponseRedirect
from catalog.forms import ProductAddToCartForm
def index(request):
context_instance = RequestContext(request)
template = "catalog/index.html"
page_title = 'Musical Instruments and Sheet Music for Musicians'
context = {'page_title': page_title,
'context_instance': context_instance}
return render(request, template, context)
def show_category(request, category_slug):
template = "catalog/category.html"
context_instance = RequestContext(request)
c = get_object_or_404(Category, slug=category_slug)
products = c.product_set.all()
page_title = c.name
meta_keywords = c.meta_keywords
meta_description = c.meta_description
context = {
'context_instance': context_instance,
'c': c,
'products': products,
'page_title': page_title,
'meta_keywords': meta_keywords,
'meta_description': meta_description,
}
return render(request, template, context)
def show_product(request, product_slug):
p = get_object_or_404(Product, slug=product_slug)
context_instance = RequestContext(request)
categories = p.categories.filter(is_active=True)
page_title = p.name
meta_keywords = p.meta_keywords
meta_description = p.meta_description
if request.method == 'POST':
postdata = request.POST.copy()
form = ProductAddToCartForm(request, postdata)
if form.is_valid():
cart.add_to_cart(request)
if request.session.test_cookie_worked():
request.session.delete_test_cookies()
return redirect('cart: show_cart')
else:
form = ProductAddToCartForm(request=request, label_suffix=':')
form.fields['product_slug'].widget.attrs['value'] = product_slug
request.session.set_test_cookie()
context = {
'context_instance': context_instance,
'p': p,
'categories': categories,
'page_title': page_title,
'meta_keywords': meta_keywords,
'meta_description': meta_description,
'form':form
}
template = "catalog/product.html"
return render(request, template, context)
urls.py:
from django.urls import path
from catalog import views
app_name = 'catalog'
urlpatterns = [
path('', views.index, name='index'),
path('<category_slug>/', views.show_category, name='show_category'),
path('product/<product_slug>', views.show_product, name='show_product'),
]
template that the form is embedded in
{% extends "catalog.html" %}
{% block content %}
{% block sidebar %}
{% endblock %}
<div class="container mt-2 pl-5">
<div class="row text-justify ml-5 pl-5">
<div class="col-md img-responsive">
<img src="{{ p.image.url }}" alt="{{ p.name }}" class="img-responsive
center-block img-thumbnail" width="100%"/>
</div>
<div class="col-md">
<h4>{{ p.name }}</h4>
Brand: <em>{{ p.brand }}</em>
<br /><br />
SKU: {{ p.sku }}
<br />
In categor{{ categories.count|pluralize:"y,ies" }}:
{% for c in categories %}
<a href="{{ c.get_absolute_url }}">{{ c.name }}</a>
{% if not forloop.last %}, {% endif %}
{% endfor %}
<br /><br />
{% if p.sale_price %}
Was: <s>$ {{ p.old_price }}</s>
<br />
Now: $ {{ p.price }}
{% else %}
Price: $ {{ p.price }}
{% endif %}
<br /><br />
<form method="POST" action=".">
{{ form.as_p }}
{% csrf_token %}
<br />
<input type="submit" value="Add To Cart" name="submit" alt="Add To Cart"
/>
</form>
</div>
</div>
<div class=" text-center pt-5 mb-5 pb-5">
<h3>Product Description</h3>
{{ p.description }}
</div>
</div>
{% endblock %}
whenever i click the add to cart, i get this error:
Page not found (404)
Request Method: POST
Request URL:http://127.0.0.1:8000/catalog/product/
Raised by:catalog.views.show_category
Upvotes: -1
Views: 158
Reputation: 222862
As you can see in your error message
Raised by:catalog.views.show_category
catalog.views.show_category
raised the error, so since it is a 404 it is probably raised by
c = get_object_or_404(Category, slug=category_slug)
Now, it is trying to search a category... Why? The url is http://127.0.0.1:8000/catalog/product/
Let's check your paths
path('<category_slug>/', views.show_category, name='show_category'),
Interesting, so any path followed by a slash calls show_category
! Not what you would want, that means that http://127.0.0.1:8000/catalog/product/
is trying to show a category with slug name 'product'
!!
Now there are multiple ways to fix it. All of them involve restructuring your paths (and changing the rest of the application accordingly)
Upvotes: 1