Django add to wishlist

Question:

I have to do wishlist, I have done wishlist page, model and html.bBut when I click on the button bellow my post, I’m redirected to wishlist page and post didnt saved in my wishlist.So thats my code:
models.py

class Wishlist(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.CASCADE)
    wished_item = models.ForeignKey(Posts, on_delete=models.CASCADE)


def __str__(self):
    return self.wished_item.title

class Posts(models.Model):
    TYPE = Choices(
        ('private', _('private')),
        ('business', _('business')),
    )
    STATUS = Choices(
        ('active', _('active')),
        ('deactivated', _('deactivated'))
    )
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, related_name='posts',
                              on_delete=models.CASCADE, verbose_name='owner')
    phone_number = PhoneNumberField(verbose_name=_('Phone_number'), null=False, blank=False, unique=True)
    title = models.CharField(verbose_name=_('Title'), max_length=100)
    text = RichTextField(verbose_name=_('Text'))
    image = models.ImageField(upload_to='images/%Y/%m/%d/', null=True, blank=True, validators=[file_size])
    price = models.DecimalField(verbose_name=_('Price'), decimal_places=2, max_digits=9)
    status = models.CharField(choices=STATUS, max_length=50)
    created = models.DateTimeField(auto_now=True)
    type = models.CharField(choices=TYPE, max_length=50)

    def __str__(self):
        return self.title

views.py

class WishListView(generic.View):
    def get(self, *args, **kwargs):
        wish_items = Wishlist.objects.filter(user=self.request.user)
        context = {
            'wish_items': wish_items
        }
        return render(self.request, 'wishlist/wishlist.html', context=context)


def addToWishList(request):
    if request.method == 'POST':
        post_var_id = request.POST.get('object-id')
        post_var = Posts.objects.get(id=post_var_id)
        print(post_var)

        try:
            wish_item = Wishlist.objects.get(user=request.user, post=post_var)
            if wish_item:
                wish_item.save()

        except:
            Wishlist.objects.create(user=request.user, post=post_var)

        finally:
            return HttpResponseRedirect(reverse('wishlist'))

wishlist.html

{% extends 'posts/base.html' %}
{% load thumbnail %}
{% block content %}
<div>
  {% for item in wish_items %}
  {% if item.wished_item.image1 %}
  <img src="{{item.wished_item.image.url}}" alt="">
  {% endif %}
</div>
<div>
  <li>{{item.wished_item.title}}</li>
  <li>{{item.wished_item.text}}</li>
  <li>{{item.wished_item.price}}</li>
  <li>{{item.wished_item.phone_number}}</li>
  {% if item.wished_item.image %}
      <img src="{% thumbnail item.wished_item.image 200x200 crop %}" alt="" />
  <p></p>
  {% endif %}
</div>
{% endfor %}
{% endblock %}

urls.py

urlpatterns = [
    path("wishlist/", WishListView.as_view(), name='wishlist'),
    path("add-to-wishlist", addToWishList, name='add-to-wishlist'),
]

and all posts template with add to wishlist button.

<ul>
    {% for object in object_list %}
    <li>Owner: {{ object.owner }}</li>
    <li>Phone: {{ object.phone_number }}</li>
    <li>Title: {{ object.title }}</li>
    <li>Text: {{ object.text }}</li>
    <li>Type: {{ object.type }}</li>
    <li>Price: {{ object.price }}</li>
    <li>Date: {{ object.created }}</li>
    <p>
      {% if object.image %}
      <img src="{% thumbnail object.image 200x200 crop %}" alt="" />
      {% endif %}
      </p>
  <form action="{% url 'add-to-wishlist' %}" method="POST">
    {%csrf_token%}
    <input type="hidden" name="object-id" value="{{object.id}}">
    <input type="submit" value="Add to Wishlist">
  </form>
  <hr/>

Probably problem with posts Id, but I’m not sure in that.

Asked By: makim

||

Answers:

In your views.py try to replace these lines:

try:
    wish_item = Wishlist.objects.get(user=request.user, post=post_var)
    if wish_item:
        wish_item.save()

except:
    Wishlist.objects.create(user=request.user, post=post_var)

with

wish_item, was_created = Wishlist.objects.get_or_create(user=request.user, post=post_var)
# for debugging
if was_created:
    print(f"{wish_item} was created")
else:
    print(f"{wish_item} already exists")

what is the output?

The code looks OK for me. You might add a trailing / in your urls.py after the path("add-to-wishlist/" ... but I can’t spot anything wrong in the first place.

Answered By: hanspeters205

You can use get_or_create instead of the if else statement for if exist or not. And use get_object_or_404 to make code more clear.

from django.shortcuts import get_object_or_404

def addToWishList(request):
    if request.method == 'POST':
        post_obj = get_object_or_404(Post, pk=request.POST.get('object-id'))
        Wishlist.objects.get_or_create(user=request.user, post=post_obj)
        return HttpResponseRedirect(reverse('wishlist'))
Answered By: enes islam