diff --git a/backend/product/admin.py b/backend/product/admin.py index 20c58cd..9fe5c5f 100644 --- a/backend/product/admin.py +++ b/backend/product/admin.py @@ -260,10 +260,10 @@ class MainCategoryModelAdmin(ModelAdmin, ImportExportModelAdmin): @admin.register(SubCategoryModel) class SubCategoryModelAdmin(ModelAdmin, ImportExportModelAdmin): - list_display = ['name', 'parent', 'show'] + list_display = ['name', 'parent'] search_fields = ['name', 'slug'] - list_filter = ['parent', 'show', ] + list_filter = ['parent', ] import_form_class = ImportForm export_form_class = ExportForm diff --git a/backend/product/migrations/0045_remove_subcategorymodel_show_maincategorymodel_image.py b/backend/product/migrations/0045_remove_subcategorymodel_show_maincategorymodel_image.py new file mode 100644 index 0000000..4dd979a --- /dev/null +++ b/backend/product/migrations/0045_remove_subcategorymodel_show_maincategorymodel_image.py @@ -0,0 +1,22 @@ +# Generated by Django 5.1.2 on 2025-05-21 10:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('product', '0044_alter_productvariant_slider_category'), + ] + + operations = [ + migrations.RemoveField( + model_name='subcategorymodel', + name='show', + ), + migrations.AddField( + model_name='maincategorymodel', + name='image', + field=models.ImageField(blank=True, null=True, upload_to='category_model/', verbose_name='عکس'), + ), + ] diff --git a/backend/product/models.py b/backend/product/models.py index 310a147..f7aacc8 100644 --- a/backend/product/models.py +++ b/backend/product/models.py @@ -10,6 +10,7 @@ class MainCategoryModel(models.Model): name = models.CharField(max_length=50, verbose_name='نام دسته بندی') slug = models.SlugField(max_length=50, unique=True, help_text="اسم دسته را برای مسیر به انگلیسی و بدون فاصله وارد کنید") icon = models.ImageField(upload_to='category_model/',verbose_name='آیکون', blank=True, null=True) + image = models.ImageField(upload_to='category_model/',verbose_name='عکس', blank=True, null=True) meta_title = models.CharField(max_length=60, verbose_name="عنوان متا", help_text="عنوان متا برای SEO", blank=True, null=True) meta_description = models.TextField(max_length=160, verbose_name="توضیحات متا", help_text="توضیحات متا برای SEO", blank=True, null=True) @@ -34,7 +35,6 @@ class SubCategoryModel(models.Model): meta_title = models.CharField(max_length=60, verbose_name="عنوان متا", help_text="عنوان متا برای SEO", blank=True, null=True) meta_description = models.TextField(max_length=160, verbose_name="توضیحات متا", help_text="توضیحات متا برای SEO", blank=True, null=True) parent = models.ForeignKey(MainCategoryModel, on_delete=models.CASCADE, related_name='subcategorys', verbose_name='دسته‌بندی والد') - show = models.BooleanField(default=False, verbose_name='نمایش در خانه') class Meta: verbose_name = "زیر دسته‌بندی" diff --git a/backend/product/serializers.py b/backend/product/serializers.py index 4cf3178..447190a 100644 --- a/backend/product/serializers.py +++ b/backend/product/serializers.py @@ -92,7 +92,7 @@ class SubCategorySerializer(serializers.ModelSerializer): parent = serializers.SerializerMethodField() class Meta: model = SubCategoryModel - fields = ['id', 'name', 'slug','icon', 'meta_title', 'meta_description', 'product_count', 'show', 'parent', 'image'] + fields = ['id', 'name', 'slug','icon', 'meta_title', 'meta_description', 'product_count', 'parent', 'image'] def get_product_count(self, obj): return obj.products.count() def get_parent(self, obj): @@ -103,7 +103,7 @@ class MainCategorySerializer(serializers.ModelSerializer): subcategorys = SubCategorySerializer(many=True) class Meta: model = MainCategoryModel - fields = ['id', 'name', 'slug', 'icon', 'meta_title', 'meta_description', 'subcategorys'] + fields = ['id', 'name', 'slug', 'icon', 'meta_title', 'meta_description', 'subcategorys', 'image'] class DynamicProductSerializer(serializers.ModelSerializer): diff --git a/backend/product/views.py b/backend/product/views.py index a1d873a..901e9fb 100644 --- a/backend/product/views.py +++ b/backend/product/views.py @@ -94,6 +94,12 @@ class AllProductsView(APIView): type=OpenApiTypes.INT, required=False, ), + OpenApiParameter( + name="category_type", + type=OpenApiTypes.STR, + required=False, + enum=['sub', 'main'], + ), OpenApiParameter( name="price_gte", description="Filter products with price greater than or equal to this value.", @@ -153,15 +159,25 @@ class AllProductsView(APIView): ) def get(self, request): try: - category_id = request.query_params.get('category', None) - if category_id: - try: - category_id = int(category_id) - except ValueError: - return Response({'detail': 'value error category id should be a number'}, status=status.HTTP_400_BAD_REQUEST) + category_slug = request.query_params.get('category') + category_type = request.query_params.get('category_type') - sub_category = get_object_or_404(SubCategoryModel, pk=category_id) - products = ProductModel.objects.filter(category=sub_category) + VALID_CATEGORY_TYPES = {'sub', 'main'} + + if category_slug: + if category_type not in VALID_CATEGORY_TYPES: + return Response( + {"detail": "category_type must be one of ['sub', 'main']"}, + status=status.HTTP_400_BAD_REQUEST + ) + + if category_type == 'sub': + sub_category = get_object_or_404(SubCategoryModel, slug=category_slug) + products = ProductModel.objects.filter(category=sub_category) + else: # category_type == 'main' + main_category = get_object_or_404(MainCategoryModel, slug=category_slug) + sub_categories = main_category.subcategorys.all() + products = ProductModel.objects.filter(category__in=sub_categories) else: products = ProductModel.objects.all() @@ -204,8 +220,10 @@ class AllProductsView(APIView): return paginator.get_paginated_response(serializer.data) except MainCategoryModel.DoesNotExist: - return Response({"detail": "Category not found."}, status=status.HTTP_404_NOT_FOUND) + return Response({"detail": "Main Category not found."}, status=status.HTTP_404_NOT_FOUND) + except SubCategoryModel.DoesNotExist: + return Response({"detail": "Sub Category not found."}, status=status.HTTP_404_NOT_FOUND) class ShowCaseCategoryListView(APIView): serializer_class = ShowCaseSliderSerialzier