Ahmed Wagdi
Ahmed Wagdi

Reputation: 4421

Ajax error with django

I'm trying to activate add to the favorite button with ajax, also the same button should remove from favorite if it is already there, here is my full files:

models.py

class Favorite(models.Model):
    item = models.ForeignKey(Item, on_delete='CASCADE')
    user = models.ForeignKey(UserModel, on_delete='CASCADE')

    class Meta:
        unique_together = (('item', 'user'), )

urls.py

path('<int:pk>/favorite_item/', views.favorite_item, name='favorite_item'),

views.py

@login_required
def favorite_item (request, pk):
    favitem = get_object_or_404(Item, pk=pk)
    data = {
        'is_fav': Favorite.objects.get(user=request.user, item=favitem).exists(),
    }

    if data ['is_fav']:
        Favorite.objects.get(user=request.user, item=favitem).delete()
    else:
        new_entry = Favorite.objects.create(item=favitem, user=request.user)

    return JsonResponse(data)

home.html

{% extends 'fostania_web_app/base.html' %}
{% block javascript %}
  <script>
    $("#add_to_fav").click(function () {
      console.log( $(this).val() );
    });
              $.ajax({
        url: form.attr("data-favorite_item-url"),
        data: form.serialize(),
        dataType: 'json',
        success: function (data) {
          if (data.is_fav) {
            alert('تم');
          }
        }
      });

    });
  </script>

  </script>
{% endblock %}
{% block content %}
{% load static %}

        {% include 'fostania_web_app/slide.html' %}

 <!-- Page Content -->
    <div class="container">

      <h1 class="my-4" align="right" dir="rtl">إستثمرى فساتينك القديمة مع Fostania</h1>

      <!-- Marketing Icons Section -->
      <div class="row">
        <div class="col-lg-4 mb-4">
          <div class="card h-100">
            <h4 class="card-header" align="right">إنشاء حساب جديد</h4>
            <div class="card-body">
              <p class="card-text" align="center"><img src="{% static 'img/add_user_big.png' %}"><Br>
                  قم بإنشاء حساب جديد على فوستانيا حتى تستطيع عرض الفستان على الموقع</p>
            </div>
            <div class="card-footer" align="right">
              <a href="{% url 'signup' %}" class="btn btn-primary" style="background: linear-gradient(to right, #ff00a4 , #871f78);border-color: #871f78;">تسجيل حساب جديد</a>
            </div>
          </div>
        </div>
        <div class="col-lg-4 mb-4">
          <div class="card h-100">
            <h4 class="card-header" align="right">عرض الفستان على الموقع</h4>
            <div class="card-body">
              <p class="card-text" align="center"><img src="{% static 'img/plus_big.png' %}"><Br>
                  قم بإضافة الفستان مجاناً على الموقع حتى يصل الى مئات المشتريين و المهتمين
              </p>
            </div>
            <div class="card-footer" align="right">
              <a href="{% url 'dress_add' %}" class="btn btn-primary" style="background: linear-gradient(to right, #ff00a4 , #871f78);border-color: #871f78;">عرض الفستان على الموقع</a>
            </div>
          </div>
        </div>
        <div class="col-lg-4 mb-4">
          <div class="card h-100">
            <h4 class="card-header" align="right">إبحثى عن الفستان المطلوب</h4>
            <div class="card-body">
              <p class="card-text" align="center"><img src="{% static 'img/search_big.png' %}"><Br>
                  او يمكن البحث عن الفستان المراد شرائه او تأجيره من وسط مئات الفساتين المعروضة</p>
            </div>
            <div class="card-footer" align="right">
              <a href="{% url 'dress_list' %}" class="btn btn-primary" style="background: linear-gradient(to right, #ff00a4 , #871f78);border-color: #871f78;">إبدأ البحث</a>
            </div>
          </div>
        </div>
      </div>
      <!-- /.row -->
        <!-- adsense -->
    <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Fostania-main -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4202417439740489"
     data-ad-slot="1170851377"
     data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
    <!-- end -->
      <!-- Portfolio Section -->
      <h2 align="right"> اخر الفساتين المضافة للموقع</h2>

      <div class="row">
          {% for dress in dresss %}
        <div class="col-lg-4 col-sm-6 portfolio-item">
          <div class="card h-100" >
            <a href="{% url 'dress_details' dress.pk%}" align="center"><img class="card-img-top" src="{{ dress.dress_image1.url }}" style='width: 200px;height: 200px;' alt=""></a>
            <div class="card-body">
              <h4 class="card-title" align="center">
                    {% if user.is_authenticated %}

                               {% if user_favs %}
                      {% for item in user_favs %}
                  {% if item.item == dress %}
                                                      <a href="{% url 'favorite_item' dress.id %}" id="add_to_fav">
                  <img src="{% static 'img/star-yes.png' %}" title="مسح من  الفساتين المفضلة"></a>
{% else %}

                                <a href="{% url 'favorite_item' dress.id %}" id="add_to_fav">
                  <img src="{% static 'img/star_no.png' %}" title="إضافة إلى الفساتين المفضلة"></a>

                          {% endif %}
                          {% endfor %}
              {% else %}
                                              <a href="{% url 'favorite_item' dress.id %}" id="add_to_fav">
                  <img src="{% static 'img/star_no.png' %}" title="إضافة إلى الفساتين المفضلة"></a>
              {% endif %}
              {% endif %}

                <a href="{% url 'dress_details' dress.pk%}">{{ dress.dress_name }}</a>
                <Br>
                <h3><span class="badge badge-warning">{{ dress.dress_price }} EGP</span></h3>
              </h4>
              <p class="card-text" align="right">
معروض {{ dress.dress_action }} <br>
                  فى محافظة {{ dress.dress_town }}
              </p>
            </div>
          </div>
        </div>
{% endfor %}
      </div>

<!-- paginator part -->
<div align="right">
        {% if dresss.has_previous %}
                        <a href="?page=1"><button class="btn btn-success">&laquo; الأولى </button></a>
            <a href="?page={{ dresss.previous_page_number }}"> <button class="btn btn-success">السابقة</button> </a>
        {% endif %}
</div>
    <div align="center">
        <span class="current" >
            صفحة رقم  {{ dresss.number }} من إجمالى {{ dresss.paginator.num_pages }}
        </span>
    </div>
    <div align="left">
        {% if dresss.has_next %}
                                    <a href="?page={{ dresss.next_page_number }}"><button class="btn btn-success">التالية</button>  </a>
            <a href="?page={{ dresss.paginator.num_pages }}"><button class="btn btn-success">الاخيرة  &raquo;</button> </a>
                    {% endif %}
</div>


      <!-- paginator part ends -->
    <hr>

      <!-- Call to Action Section -->

    <!-- /.container -->
{% endblock %}

And finally it gives me an error

DoesNotExist at /3/favorite_item/ Favorite matching query does not exist.

I made it as normal request which reloads when the user clicks it and it is working perfectly, but i need to Use Ajax to prevent the page from reloading.

Upvotes: 0

Views: 52

Answers (2)

wholevinski
wholevinski

Reputation: 3828

If a Favorite doesn't exist for an Item, this will raise because you're using get(). get() raises if an object is not found: https://docs.djangoproject.com/en/2.0/ref/models/querysets/#django.db.models.query.QuerySet.get

What I think you want is a combination of filter() and exists() like this:

    data = {
        'is_fav': Favorite.objects.filter(user=request.user, item=favitem).exists(),
    }

Upvotes: 1

Druta Ruslan
Druta Ruslan

Reputation: 7412

i think that you need to use POST method for you ajax call

<script>
    $("#add_to_fav").click(function () {
        console.log( $(this).val() );
    });
    $.ajax({
        url: form.attr("data-favorite_item-url"),
        data: form.serialize(),
        dataType: 'json',
        method: 'POST', # <- here
        ...
    });
});
</script>

Upvotes: 1

Related Questions