UserFavorites system
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 5.1.2 on 2025-10-23 08:50
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('account', '0029_shopmodel'),
|
||||
('product', '0055_alter_productmodel_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='UserFavorites',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('products', models.ManyToManyField(blank=True, to='product.productmodel', verbose_name='Likes')),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'User Favorites',
|
||||
'verbose_name_plural': 'Users Favorites',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -292,4 +292,17 @@ class SecurityBreachAttemptModel(models.Model):
|
||||
# description = models.TextField()
|
||||
|
||||
# def __str__(self):
|
||||
# return f'{self.subject[:30]}'
|
||||
# return f'{self.subject[:30]}'
|
||||
|
||||
from product.models import ProductModel
|
||||
|
||||
class UserFavorites(models.Model):
|
||||
user = models.OneToOneField(User, verbose_name=_('User'), on_delete=models.CASCADE)
|
||||
products = models.ManyToManyField(ProductModel, verbose_name=_('Likes'), blank=True,)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.user} likes'
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("User Favorites")
|
||||
verbose_name_plural = _("Users Favorites")
|
||||
@@ -17,5 +17,7 @@ urlpatterns = [
|
||||
path('unsubscribe', views.UnsubscribeView.as_view(), name='unsubscibe'),
|
||||
path('attack/view/<int:pk>', views.ChangeViewAttack.as_view(), name='attack-view'),
|
||||
path('logout', views.LogoutView.as_view(), name='logout'),
|
||||
path('notification/all', views.NotificationListAPIView.as_view(), name='notif-list')
|
||||
path('notification/all', views.NotificationListAPIView.as_view(), name='notif-list'),
|
||||
path('favorites', views.FavoritesView.as_view(), name='favorites'),
|
||||
path('favorites/toggle', views.ToggleFavoriteView.as_view(), name='favorite-toggle'),
|
||||
]
|
||||
@@ -355,3 +355,77 @@ class NotificationListAPIView(APIView):
|
||||
|
||||
def str_to_bool(self, val):
|
||||
return True if val and val == 'read' else False
|
||||
from product.models import ProductModel
|
||||
class AddToFavoritesSerializer(serializers.Serializer):
|
||||
product_slug = serializers.SlugField(allow_unicode=True)
|
||||
|
||||
def validate_product_id(self, value):
|
||||
if not ProductModel.objects.filter(slug=value).exists():
|
||||
raise serializers.ValidationError("Product does not exist.")
|
||||
return value
|
||||
|
||||
|
||||
from product.serializers import DynamicProductSerializer
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
class ToggleFavoriteView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@extend_schema(
|
||||
request=AddToFavoritesSerializer,
|
||||
responses={200: DynamicProductSerializer},
|
||||
tags=["favorites"]
|
||||
)
|
||||
def post(self, request):
|
||||
serializer = AddToFavoritesSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
product_slug = serializer.validated_data["product_slug"]
|
||||
product = get_object_or_404(ProductModel, slug=product_slug)
|
||||
|
||||
user_fav, _ = UserFavorites.objects.get_or_create(user=request.user)
|
||||
|
||||
if product in user_fav.products.all():
|
||||
user_fav.products.remove(product)
|
||||
action = "removed"
|
||||
else:
|
||||
user_fav.products.add(product)
|
||||
action = "added"
|
||||
|
||||
return Response(
|
||||
{
|
||||
"action": action,
|
||||
"product": DynamicProductSerializer(product, context={'request': request, 'view_type': 'list'}).data
|
||||
},
|
||||
status=status.HTTP_200_OK
|
||||
)
|
||||
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes
|
||||
from utils.pagination import StructurePagination
|
||||
class FavoritesView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
serializer_class = DynamicProductSerializer
|
||||
pagination_class = StructurePagination
|
||||
@extend_schema(
|
||||
tags=["favorites"],
|
||||
parameters=[
|
||||
OpenApiParameter(
|
||||
name="limit",
|
||||
description="Number of results to return per page (pagination).",
|
||||
required=False,
|
||||
type=OpenApiTypes.INT,
|
||||
),
|
||||
OpenApiParameter(
|
||||
name="offset",
|
||||
description="The starting position of the results (pagination).",
|
||||
required=False,
|
||||
type=OpenApiTypes.INT,
|
||||
),
|
||||
]
|
||||
)
|
||||
def get(self, request):
|
||||
user_fav, _ = UserFavorites.objects.get_or_create(user=request.user)
|
||||
products = user_fav.products.all()
|
||||
paginator = self.pagination_class()
|
||||
paginated_products = paginator.paginate_queryset(products, request)
|
||||
serializer = self.serializer_class(instance=paginated_products, many=True, context={'request': request, 'view_type': 'list'})
|
||||
return paginator.get_paginated_response(serializer.data)
|
||||
@@ -112,6 +112,7 @@ class DynamicProductSerializer(serializers.ModelSerializer):
|
||||
category = SubCategorySerializer(read_only=True)
|
||||
is_new = serializers.SerializerMethodField()
|
||||
related_products = serializers.SerializerMethodField()
|
||||
added_to_favorites = serializers.SerializerMethodField()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -131,10 +132,23 @@ class DynamicProductSerializer(serializers.ModelSerializer):
|
||||
view_type = {
|
||||
'list': ['id','name', 'rating', 'slug', 'category', 'variants', 'colors'],
|
||||
'slider': ['id','name', 'rating', 'slug', 'category', 'variants', 'colors'],
|
||||
'instance': ['id', 'name', 'description', 'rating', 'slug', 'meta_description', 'meta_keywords', 'meta_rating', 'category', 'related_products', 'in_pack_items', 'variants', 'colors'],
|
||||
'instance': ['id', 'name', 'description', 'rating', 'slug', 'meta_description', 'meta_keywords', 'meta_rating', 'category', 'related_products', 'in_pack_items', 'variants', 'colors', 'added_to_favorites'],
|
||||
'chat': ['id', 'name', 'description', 'variants']
|
||||
}
|
||||
|
||||
def get_added_to_favorites(self, obj):
|
||||
from account.models import UserFavorites
|
||||
request = self.context.get('request')
|
||||
if not request or not request.user.is_authenticated:
|
||||
return False # not logged in users haven't added anything
|
||||
|
||||
try:
|
||||
user_fav = UserFavorites.objects.get(user=request.user)
|
||||
except UserFavorites.DoesNotExist:
|
||||
return False
|
||||
|
||||
return obj in user_fav.products.all()
|
||||
|
||||
def get_variants(self, obj):
|
||||
view_type = self.context.get('view_type')
|
||||
if view_type == 'slider':
|
||||
|
||||
Reference in New Issue
Block a user