NoReverseMatch at /products/ "adding products to the basket" - django

I am fairly new and working on a project and want to just add products to the basket
I have struggled with this for a few days and just don't know what to do to make it work.
can anybody help me or refer me to some page that can help me?
Thank You
NoReverseMatch at /products/
Reverse for 'addtobasket' with arguments '('Python Tutorial',)' not found. 1 pattern(s) tried: ['productapp/\.\./basket/$']
models:
class Products(models.Model):
products_name = models.CharField(max_length=30)
pub_date = models.DateTimeField(auto_now=True)
price = models.CharField(max_length=10)
note = models.CharField(max_length=200)
inventory = models.IntegerField(default=1)
product_pic = models.ImageField(upload_to ='images/', default='images/broken/broken.png')
def __str__(self):
if (self.inventory<=0):
return self.products_name + ' (Out of Stock)'
return self.products_name
class Basket(models.Model):
products = models.ForeignKey(Products, on_delete=models.CASCADE)
pub_date = models.DateTimeField(auto_now=True)
amount = models.IntegerField(default=1)
def __str__(self):
return str(self.products)
urls:
app_name = 'productapp'
urlpatterns = [
path('products/', views.products, name='products'),
path('basket/', views.basket, name ='basket'),
path('', views.home, name='home'),
path('../basket/', views.addtobasket, name='addtobasket'),
]
views:
def products(request):
products_list = Products.objects.order_by('-pub_date')
context = {'products_list': products_list}
return render(request, 'productapp/products.html', context)
def basket(request):
basket_list = Basket.objects.order_by('-pub_date')
context = {'basket_list': basket_list}
return render(request, 'productapp/basket.html', context)
def addtobasket(request, name):
basket = Basket.objects.all()
product = Products.objects.get(products_name=name)
basket.products.add(product)
return HttpResponseRedirect(reverse("basket"))
html:
<body>
<section>
{% block content %}
{% if products_list %}
{% for product in products_list %}
<div>
<div>
<p>{{product.products_name}}</p>
<p>{{product.price}}</p>
Add to Basket
</div>
</div>]
{% endfor %}
{% else %}
<p>No products avalable at this moment.</p>
{% endif %}
{% endblock %}
</section>
</body>

A path with ../ makes not much sense, since that means the url should contain the dots.
Furthermore you should specify the URL parameter in the path:
app_name = 'productapp'
urlpatterns = [
path('products/', views.products, name='products'),
path('basket/', views.basket, name ='basket'),
path('', views.home, name='home'),
path('basket/add/<str:name>/', views.addtobasket, name='addtobasket'),
]
Adding an item to the basket should not work with a GET request, since the HTTP protocol specifies that GET requests should not have side-effects. You will need to work with a POST request, for example by implementing a mini-form with method="post", or through an AJAX post request.

Related

Django Error - NoReverseMatch at /listings/1. Reverse for 'addcomment' with arguments '('',)' not found. (Creating a comment section)

I'm new to Django and I think I'm having issues setting up a dynamic url. I'm creating a way to add comments to a page, called a listing. The listing page loaded fine before I added anything about comments. When I try to go to that particular listing, I get the error:
"NoReverseMatch at /listings/1. Reverse for 'addcomment' with arguments '('',)' not found. 1 pattern(s) tried: ['addcomment/(?P[0-9]+)$']"
Any help is appreciated because even after looking at the documentation I am having trouble understanding how dynamic urls work/how to create them.
I think my html page might also have problems, in terms of pulling in the correct info with the url etc.
views.py
def addcomment(request, id):
obj = Comments()
obj.comment = request.POST.get("comment")
obj.user = request.user.username
obj.listingid = id
obj.save()
# returning the updated content
print("displaying comments")
comments = Comments.objects.filter(listingid=id)
product = Listings.objects.filter(id=id)
return render(request, "auctions/listing.html", {
"product": product,
"comments": comments
})
def listingpage(request, id):
comments = Comments.objects.get(listingid=id)
item = Listings.objects.get(id=id)
return render(request, "auctions/listing.html", {
"i": item,
"id": id,
"comments": comments,
})
urls.py
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("auctions/create", views.create, name="create"),
path("listings/<int:id>", views.listingpage, name="listingpage"),
path("addcomment/<int:id>", views.addcomment, name="addcomment"),
]
models.py
class Listings(models.Model):
title = models.CharField(max_length=64)
description = models.TextField(max_length=250)
starting_bid = models.IntegerField()
link = models.CharField(max_length=100, default=None, blank=True,
null=True)
class Comments(models.Model):
comment = models.CharField(max_length=250, default='')
user = models.CharField(max_length=64)
listingid = models.IntegerField()
Part of the HTML file for the listing page that adds comments:
<h2 class="card-title h2">ADD COMMENT</h2>
<form action="{% url 'addcomment' product.id %}"
method="POST">
{% csrf_token %}
<div class="form-group">
<textarea class="form-control" name="comment"
rows="4" placeholder="Your Comment"></textarea>
</div>
<p align="justify"><input class="btn btn-primary" type="submit" value="Submit"></p>
</form>
</div>
{% endblock %}
The problem is that you did not pass a variable with the name product to the listing.html template, only i, id, and comments. You thus should pass this as product:
def listingpage(request, id):
comments = Comments.objects.get(listingid=id)
item = Listings.objects.get(id=id)
return render(request, 'auctions/listing.html', {
'i': item,
'id': id,
'product': item, # &leftarrow; pass product
'comments': comments,
})

ValueError: The 'cover' attribute has no file associated with it

I uploaded image from admin panel and it get stored in media/img.I want to display posted image in my index.html but i get this ValueError: The 'cover' attribute has no file associated with it.I think I am making mistake in url or view ..I am new to django.
# app urls.py
urlpatterns = [
path('', views.PostList.as_view(), name='home'),
path('<slug:slug>/', views.post_detail, name='post_detail'),
]
# project urls.py
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("blog.urls"), name="blog-urls"),
path("summernote/", include("django_summernote.urls")),
]
# views.py
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'index.html'
paginate_by = 3
# models.py
class Post(models.Model):
cover = models.ImageField(upload_to='image/', default='')
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="blog_posts"
)
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
<!-- index.html -->
<img src={{ post.cover.url }} alt="{{ post.title }}" width="160px" height="220px">
List view output is a queryset, means a list of instances, so you have to loop through it.
{% for post in object_list %}{% if post.cover %}
<img src={{ post.cover.url }} alt="{{ post.title }}" width="160px" height="220px">{% endif %}
{% endfor %}
also change the include url to
path("", include("blog.urls"))
without name, if you want you can add a namespace

reverse url link within list view template

i created methods within my model class to handle my redirects all work except for the one i created for a link in my list view(go_to_create method ) im using class based views
class Todo(models.Model):
name = models.CharField(max_length=100, default='unamedTodo')
description = models.CharField(max_length=200)
Todo_date = models.DateTimeField('Todo Date')
pub_date = models.DateTimeField('Date Published')
def get_absolute_url(self):
return reverse('ToDo:detail', kwargs={'id': self.id})
def get_back_home(self):
return reverse('ToDo:todos', kwargs={})
def go_to_update(self):
return reverse('ToDo:update', kwargs={'id': self.id})
def go_to_create(self):
return reverse('ToDo:create', kwargs={})
class TodoCreateView(CreateView):
template_name = 'ToDo/todo_create.html'
form_class = TodoForm
queryset = Todo.objects.all()
from django.urls import path
from .views import (
TodoListView,
TodoDetailView,
TodoCreateView,
TodoUpdateView,
TodoDeleteView,
)
app_name = "ToDo"
urlpatterns = [
path('Todos/', TodoListView.as_view(), name='todos'),
path('Todos/<int:id>/', TodoDetailView.as_view(), name='detail'),
path('Todos/create/', TodoCreateView.as_view(), name='create'),
path('Todos/<int:id>/update/', TodoUpdateView.as_view(), name='update'),
path('Todos/<int:id>/delete/', TodoDeleteView.as_view(), name='delete')
]
<h1>ToDo's</h1>
<ul>
{% for object in object_list %}
<li>
<p>
{{ object.id }} -
{{ object.name }}
</p>
</li>
{% endfor %}
<p>Create new Todo here</p>
</ul>
the link calling the go_to_create method does not work i stay on the same page no error is generated
Instead of a method call directly on template,that will do the job.
{% url 'ToDo:create' %}

url path from categories in DetailView

I use a DetailView to display all elements inside a category.
I am trying to get my category slugs as variables in urls. But I don't know how to make the link between categories and details.
So far when I click on one of the generated link in the Index.html such as http://localhost:8000/oneofthecategories, I get the following error:
Exception Type: FieldError
Exception Value:
Cannot resolve keyword 'slug' into field. Choices are: author, category, category_id, id, title
Files:
#Models.py
class categories(models.Model):
name = models.CharField(max_length=50,unique=True)
slug = models.SlugField(max_length=100,unique=True)
def __str__(self):
return self.name
class details(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=42)
category = models.ForeignKey('categories', on_delete=models.CASCADE,related_name="detail")
def __str__(self):
return self.title
#Views.py
class IndexView(generic.ListView):
model = categories
context_object_name = "list_categories"
template_name='show/index.html'
class CategoryDetails(DetailView):
model = details
context_object_name = "detail"
template_name = "show/categories.html"
slug_url_kwarg = 'slug'
#Urls.py
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<slug:slug>', views.CategoryDetails.as_view(), name='category_details'),
]
#Index.html
{% load staticfiles %}
<p>These is a list of categories</p>
{% for category in list_categories %}
<div class="article">
<h3>{{ category.name }}</h3>
{% for detail in category.categories.all %}
<p> {{detail.title}} </p>
<li>URLS</li>
{% endfor %}
</div>

Django dynamic filtering by passing slug from template

So I've read this article on dynamic filtering in Django; Dynamic filtering
Though I had something working I needed two similar views, one to show all different categories with their slug as parameter, and a second view to show all posts from all categories without a parameter.
How can I use a single ListView and pass an empty parameter from the template to show all posts from all categories in a list?
Or would this even be possible?
urls.py
urlpatterns = [
path('', views.PostListView.as_view(), name='index'),
path('<slug:slug>/', views.PostbyCategoryListView.as_view(), name="category"),
]
views.py
class PostListView(ListView):
model = Post
template_name = 'index.html'
class PostbyCategoryListView(ListView):
model = Post
template_name = 'index.html'
def get_queryset(self):
self.category = get_object_or_404(Category, slug=self.kwargs['slug'])
return Post.objects.filter(category=self.category)
index.html
...
<h6>Categories</h6>
{% if category_list %}
<ul>
<li class="category-item">
All categories
</li>
{% for category in category_list %}
<li class="category-item">
{{ category.name }}
</li>
{% endfor %}
</ul>
{% else %}
<p>No categories</p>
{% endif %}
...
models.py
class Category(models.Model):
name = models.CharField(max_length=200)
slug = models.CharField(max_length=200)
class Post(models.Model):
category = models.ForeignKey('Category',default=1, on_delete=models.SET_NULL, null=True, related_name="posts")
title = models.CharField(max_length=200)
content = models.TextField(max_length=2000)