I'm not sure of why I can't get the pk which I think it's the problem here. I am trying to do a like functionality to a product model, with a like the page would refresh and the result be shown but it does not save the like and the error Page not found (404) No Product matches the given query.
My Model:
class Product(models.Model):
author = models.ForeignKey(User, default=None, on_delete=models.CASCADE)
title = models.CharField(max_length=120, unique=True)
likes = models.ManyToManyField(User, related_name='like')
...
def number_of_likes(self):
return self.likes.count()
My views:
class ProductDetailView(DetailView):
model = Product
template_name = 'services/product_detail.html'
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
likes_connected = get_object_or_404(Product, id=self.kwargs['pk'])
liked = False
if likes_connected.likes.filter(id=self.request.user.id).exists():
liked = True
data['number_of_likes'] = likes_connected.number_of_likes()
data['post_is_liked'] = liked
return data
def ProductLike(request, pk):
post = get_object_or_404(Product, id=request.POST.get('product_id'))
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
else:
post.likes.add(request.user)
return HttpResponseRedirect(reverse('product-detail', args=[str(pk)]))
My urls:
path('product/<int:pk>/', ProductDetailView.as_view(), name='product-detail'),
path('product-like/<int:pk>/', ProductLike, name="product_like"),
My template:
{% if user.is_authenticated %}
<form action="{% url 'product_like' object.id %}" method="POST">
{% csrf_token %}
{% if post_is_liked %}
<button type="submit" name="blogpost_id" value="{{object.id}}" >Unlike</button>
{% else %}
<button type="submit" name="blogpost_id" value="{{object.id}}">Like</button>
{% endif %}
</form>
{% else %}
<a href="{% url 'login' %}?next={{request.path}}">Log in to like this article!</a><br>
{% endif %}
<strong>{{ number_of_likes }} Like{{ number_of_likes|pluralize }}</strong>
CodePudding user response:
A couple of things that could be giving you problems:
In your redirect for ProductLike you use args
return HttpResponseRedirect(reverse('product-detail', args=[str(pk)]))
But when you get back to the view, you are looking for kwargs
likes_connected = get_object_or_404(Product, id=self.kwargs['pk'])
Try using kwargs in your redirect
return HttpResponseRedirect(reverse('product-detail', kwargs={'pk': pk}))
Also, in your ProductLike view you are referring to request.POST.get('product_id'))
However, you are not sending any fields by the name product_id
. It looks like the like form sends blogpost_id
, so the lookup in the view will always 404.