complete base of product and categories
This commit is contained in:
@@ -1,6 +1,58 @@
|
||||
from django.db import models
|
||||
from django.utils.text import slugify
|
||||
from django.contrib.auth.models import User
|
||||
from django.urls import reverse
|
||||
|
||||
class CategoryModel(models.Model):
|
||||
name = models.CharField(max_length=50, verbose_name='نام دستهبندی')
|
||||
slug = models.SlugField(
|
||||
max_length=50,
|
||||
unique=True,
|
||||
help_text="اسم دسته را برای مسیر به انگلیسی و بدون فاصله وارد کنید"
|
||||
)
|
||||
parent = models.ForeignKey(
|
||||
'self',
|
||||
on_delete=models.CASCADE,
|
||||
related_name='children',
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name='دستهبندی والد'
|
||||
)
|
||||
icon = models.CharField(max_length=100, 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
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "دستهبندی"
|
||||
verbose_name_plural = "دستهبندیها"
|
||||
ordering = ['parent__id', 'id'] # Optional: to order by hierarchy
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('category_detail', kwargs={'slug': self.slug})
|
||||
|
||||
def get_breadcrumb(self):
|
||||
breadcrumb = []
|
||||
category = self
|
||||
while category:
|
||||
breadcrumb.append(category)
|
||||
category = category.parent
|
||||
return breadcrumb[::-1]
|
||||
|
||||
class ProductModel(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
description = models.TextField()
|
||||
|
||||
@@ -1,9 +1,29 @@
|
||||
from .models import *
|
||||
from rest_framework import serializers
|
||||
|
||||
class ProductSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = ProductModel
|
||||
fields = "__all__"
|
||||
read_only_fields = "__all__"
|
||||
|
||||
|
||||
class CommentSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = CommentModel
|
||||
fields = "__all__"
|
||||
read_only_fields = ('show', 'product')
|
||||
read_only_fields = ('show', 'product')
|
||||
|
||||
|
||||
class CategorySerializer(serializers.ModelSerializer):
|
||||
children = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Category
|
||||
fields = ['id', 'name', 'slug', 'icon', 'meta_title', 'meta_description', 'parent', 'children']
|
||||
|
||||
def get_children(self, obj):
|
||||
children = obj.children.all()
|
||||
if children.exists():
|
||||
return CategorySerializer(children, many=True).data
|
||||
return []
|
||||
@@ -0,0 +1,10 @@
|
||||
from django.urls import path
|
||||
from .views import AllCategories, ProductView, AllProductsView, CommentView
|
||||
|
||||
urlpatterns = [
|
||||
path('categories/', AllCategories.as_view(), name='all-categories'),
|
||||
path('products/<int:pk>/', ProductView.as_view(), name='product-detail'),
|
||||
path('categories/<int:pk>/products/', AllProductsView.as_view(), name='category-products'),
|
||||
path('products/<int:pk>/comments/', CommentView.as_view(), name='product-comments'),
|
||||
path('comments/<int:pk>/', CommentView.as_view(), name='comment-delete'),
|
||||
]
|
||||
@@ -7,6 +7,35 @@ from rest_framework.response import Response
|
||||
from django.db.models import Q
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework.permissions import IsAuthenticatedOrReadOnly
|
||||
from utils.pagination import StructurePagination
|
||||
|
||||
class AllCategories(APIView):
|
||||
serializer_class = CategorySerializer
|
||||
def get(self, request):
|
||||
categories = CategoryModel.objects.all()
|
||||
categories_ser = self.serializer_class(instance=categories, many=True)
|
||||
return Response({"categories": categories_ser.data}, status=status.HTTP_200_OK)
|
||||
|
||||
class ProductView(APIView):
|
||||
serializer_class = ProductModel
|
||||
def get(self, request, pk):
|
||||
product = get_object_or_404(ProductModel, id=pk)
|
||||
product_ser = self.serializer_class(instance=product, many=False)
|
||||
return Response({"product": product_ser.data}, status=status.HTTP_200_OK)
|
||||
|
||||
class AllProductsView(APIView):
|
||||
serializer_class = ProductSerializer
|
||||
pagination_class = StructurePagination
|
||||
def get(self, request, pk):
|
||||
try:
|
||||
category = Category.objects.get(pk=pk)
|
||||
products = Product.objects.filter(category__in=category.get_descendants(include_self=True))
|
||||
paginator = self.pagination_class()
|
||||
paginated_products = paginator.paginate_queryset(products, request)
|
||||
serializer = self.serializer_class(paginated_products, many=True)
|
||||
return paginator.get_paginated_response(serializer.data)
|
||||
except Category.DoesNotExist:
|
||||
return Response({"detail": "Category not found."}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
|
||||
class CommentView(APIView):
|
||||
|
||||
Reference in New Issue
Block a user