Search code examples
djangodjango-modelsdjango-viewsdjango-templates

No Watchlist matches the given query


Trying to add an item to my watchlist suddenly started returning an error

No Watchlist matches the given query.

Here is what my code looks like.

models.py

class Listing(models.Model):
    product_name = models.CharField(max_length=64, verbose_name="product_name")
    product_description = models.TextField(max_length=200, verbose_name="product description")
    product_image = models.ImageField(upload_to="images/", verbose_name="image", blank=True)
    is_active = models.BooleanField(blank=False, default=True)
    initial_price = models.DecimalField(decimal_places=2, max_digits=6, default=False)
    owner = models.ForeignKey(User, related_name="auction_owner", on_delete=models.CASCADE, default=True)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="category")
    
    def __str__(self):
        return self.product_name

class Watchlist(models.Model):
    user = models.OneToOneField(User, on_delete=models.DO_NOTHING)
    items = models.ManyToManyField(Listing, null=True, related_name="watchlist_item")

views.py

def add_to_watchlist(request, item_id):
item = get_object_or_404(Listing, pk=item_id)
user_watchlist = get_object_or_404(Watchlist, user=request.user)
user_watchlist.items.add(item)
return redirect("watchlist")

urls.py

path("add_to_watchlist/<int:item_id>", views.add_to_watchlist, name="add_to_watchlist"),

template

<div class="btn-groups">
      {% if listing in watchlist_items %}
      <a href="{% url 'remove_from_watchlist' item_id=listing.id %}" class="fas fa-shopping-cart"><button type = "button" class = "add-cart-btn">remove from watchlist</button></a>
      {% else %}
      <a href="{% url 'add_to_watchlist' item_id=listing.id %}" class="fas fa-shopping-cart"><button type = "button" class = "add-cart-btn">add to watchlist</button></a>
      {% endif %}
</div>

Solution

  • That's because for that user, no Watchlist was added yet, you can create one if missing with:

    def add_to_watchlist(request, item_id):
        item = get_object_or_404(Listing, pk=item_id)
        user_watchlist, __ = Watchlist.objects.get_or_create(user=request.user)
        user_watchlist.items.add(item)
        return redirect('watchlist')

    Note: Section 9 of the HTTP protocol specifies that requests like GET and HEAD should not have side-effects, so you should not change entities with such requests. Normally POST, PUT, PATCH, and DELETE requests are used for this. In that case you make a small <form> that will trigger a POST request, or you use some AJAX calls. Some browsers look for links and exhaustively already cache the responses of such links, so these might trigger such views with side-effects.