Files
santeh-ray/favorites/views.py
Azimkin 29d8302a4f
All checks were successful
Build and Push Docker Image / build (push) Successful in 51s
feat: add favorites feature for users
- Implemented `Favorite` model with unique user-item constraint and timestamped records
- Added `favorites:index` and `favorites:toggle` views with AJAX support for toggling favorites
- Built templates and front-end assets for the favorites page and integration with item grids
- Extended header with favorites link and dynamic counter
- Added tests covering models, views, and templates for the favorites functionality
- Updated admin to enable management of favorites via Django admin interface
2026-05-10 20:06:12 +02:00

74 lines
2.4 KiB
Python

from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import HttpRequest, HttpResponse, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils.http import url_has_allowed_host_and_scheme
from django.views.decorators.http import require_POST
from favorites.models import Favorite
from items.models import Item
def wants_json_response(request: HttpRequest) -> bool:
return (
request.headers.get("x-requested-with") == "XMLHttpRequest"
or "application/json" in request.headers.get("accept", "")
)
@login_required
def index(request: HttpRequest) -> HttpResponse:
favorite_records = (
Favorite.objects.filter(user=request.user)
.select_related("item__category", "item__subcategory")
.prefetch_related("item__images")
.order_by("-created_at", "-id")
)
items = [favorite.item for favorite in favorite_records]
return render(request, "favorites/index.html", {
"items": items,
"favorite_count": len(items),
"favorite_item_ids": {item.id for item in items},
})
@login_required
@require_POST
def toggle(request: HttpRequest) -> HttpResponse:
item_id = request.POST.get("item_id")
item = get_object_or_404(Item, pk=item_id)
favorite = Favorite.objects.filter(user=request.user, item=item).first()
if favorite:
favorite.delete()
is_favorite = False
message = f"Товар «{item.name}» удалён из избранного."
else:
Favorite.objects.create(user=request.user, item=item)
is_favorite = True
message = f"Товар «{item.name}» добавлен в избранное."
favorite_count = Favorite.objects.filter(user=request.user).count()
next_url = request.POST.get("next") or reverse("favorites:index")
if wants_json_response(request):
return JsonResponse({
"item_id": item.pk,
"is_favorite": is_favorite,
"favorite_count": favorite_count,
"message": message,
})
messages.success(request, message)
if not url_has_allowed_host_and_scheme(
next_url,
allowed_hosts={request.get_host()},
require_https=request.is_secure(),
):
next_url = reverse("favorites:index")
return redirect(next_url)