Django - кнопка добавления в избранное в ListView
Я хочу создать функцию добавления в избранное в ListView, но у меня возникают трудности с передачей slug продукта в каждом элементе.
У меня есть таблица с названием продукта и действием (кнопки Добавить/Удалить). Я хочу позволить пользователям добавлять определенный продукт в избранное или удалять его оттуда.
models.py
class Product(models.Model):
[...]
favourite = models.ManyToManyField(User, default=None, blank=True, related_name='favourite_product')
slug = models.SlugField(unique=True, blank=True, max_length=254)
views.py
@login_required
def products_in_favourites(request, slug):
product = get_object_or_404(Product, slug=slug)
added_to_favourite = False
if product.favourite.filter(id=request.user.id).exists():
product.favourite.remove(request.user)
added_to_favourite = False
else:
product.favourite.add(request.user)
added_to_favourite = True
context = {
'object': product,
'added_to_favourite': added_to_favourite,
}
if request.is_ajax():
html = render_to_string('favourite.html', context, request=request)
return JsonResponse({'form': html})
class AddToFavourite(LoginRequiredMixin, ListView):
template_name = "AddToFavourite.html"
model = Product
queryset = Product.objects.all()
context_object_name = 'product_list'
def get_context_data(self, **kwargs):
context = super(AddToFavourite, self).get_context_data(**kwargs)
product_item = get_object_or_404(Product, slug=self.kwargs['slug']) # how to pass slug of each product item here?
added_to_favourite = False
if product_item.cart.filter(id=self.request.user.id).exists():
added_to_favourite = True
context['added_to_favourite'] = added_to_favourite
AddToFavourite.html
{% block body %}
<section class="container">
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Product</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody id="favourite">
{% for product in product_list %}
<tr>
<td>{{product.title}}</td>
<td>
{% include 'favourite.html' %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</section>
{% endblock body %}
{% block javascript_files %}
<script>
$(document).ready(function(event){
$(document).on('click', '#favourite', function(event){
event.preventDefault();
var slug = $(this).attr('value');
$.ajax({
type: 'POST',
url: '{% url "products_in_favourites" product.slug %}',
data: {
'slug':slug,
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
dataType: 'json',
success: function(response){
$('#favourite-section').html(response['form'])
},
error: function(rs, e){
console.log(rs.responseText);
},
});
});
});
</script>
{% endblock javascript_files %}
favourite.html
<form action="{% url 'products_in_favourites' product.slug %}" method="POST" class="mx-3">
{% csrf_token %}
{% if added_to_favourite %}
<button type="submit" id="favourite" name="product_slug", value="{{product.slug}}">Remove</button>
{% else %}
<button type="submit" id="favourite" name="product_slug", value="{{product.slug}}">Add</button>
{% endif %}
</form>
urls.py
urlpatterns = [
path('add-to-favourite/', views.AddToFavourite.as_view(), name='cost_calculator'),
path('add-to-favourite/<slug:slug>', views.products_in_favourites, name='products_in_favourites'),
]
Вы посылаете свою пулю не в ListView
Вы посылаете ее
<form action="{% url 'products_in_favourites' product.slug %}" method="POST" class="mx-3">
в функцию products_in_favourites
, и делает это неправильно в части получения,
Вы не посылаете его в функцию как slug
, вы посылаете его как data
с post reqeust
, и поэтому вы должны получить его таким же образом:
@login_required
def products_in_favourites(request):
#print all data to see what is coming to this view
print(request.POST)
slug = request.POST['product_slug']
product = get_object_or_404(Product, slug=slug)
Также лучше передавать pk (первичный ключ) вместо slug, первичный ключ по умолчанию имеет индексы в базе данных, поэтому ваш запрос будет намного быстрее, если вы используете pk.