From a7aea4ed42c3bedab9736217edf0029c7a541928 Mon Sep 17 00:00:00 2001 From: behruz-dev Date: Tue, 2 Sep 2025 14:11:26 +0500 Subject: [PATCH] add: add new model and api for products --- .dockerignore | 1 + core/apps/products/admin/product.py | 9 ++++-- .../migrations/0003_unity_product_unity.py | 32 +++++++++++++++++++ core/apps/products/models/product.py | 15 +++++++-- core/apps/products/serializers/product.py | 11 +++++-- core/apps/products/urls.py | 1 + core/apps/products/views/product.py | 19 ++++++++--- 7 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 core/apps/products/migrations/0003_unity_product_unity.py diff --git a/.dockerignore b/.dockerignore index e69de29..5ceb386 100644 --- a/.dockerignore +++ b/.dockerignore @@ -0,0 +1 @@ +venv diff --git a/core/apps/products/admin/product.py b/core/apps/products/admin/product.py index 0b77042..f335fed 100644 --- a/core/apps/products/admin/product.py +++ b/core/apps/products/admin/product.py @@ -2,10 +2,15 @@ from django.contrib import admin from modeltranslation.admin import TranslationAdmin -from core.apps.products.models import Product +from core.apps.products.models import Product, Unity @admin.register(Product) class ProductAdmin(TranslationAdmin): list_display = ['id', 'name', 'price', 'category'] - list_filter = ['category'] \ No newline at end of file + list_filter = ['category'] + + +@admin.register(Unity) +class UnityAdmin(admin.ModelAdmin): + list_display = ['id', 'name'] \ No newline at end of file diff --git a/core/apps/products/migrations/0003_unity_product_unity.py b/core/apps/products/migrations/0003_unity_product_unity.py new file mode 100644 index 0000000..23bf163 --- /dev/null +++ b/core/apps/products/migrations/0003_unity_product_unity.py @@ -0,0 +1,32 @@ +# Generated by Django 5.2 on 2025-09-02 14:04 + +import django.db.models.deletion +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('products', '0002_category_name_ru_category_name_uz_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='Unity', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('name', models.CharField(max_length=200)), + ], + options={ + 'verbose_name': 'Birlik', + 'verbose_name_plural': 'Birliklar', + }, + ), + migrations.AddField( + model_name='product', + name='unity', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='products', to='products.unity'), + ), + ] diff --git a/core/apps/products/models/product.py b/core/apps/products/models/product.py index 5206fc2..e7c36e1 100644 --- a/core/apps/products/models/product.py +++ b/core/apps/products/models/product.py @@ -4,17 +4,28 @@ from core.apps.shared.models.base import BaseModel from core.apps.products.models import Category +class Unity(BaseModel): + name = models.CharField(max_length=200) + + def __str__(self): + return self.name + + class Meta: + verbose_name = 'Birlik' + verbose_name_plural = 'Birliklar' + + class Product(BaseModel): name = models.CharField(max_length=200) image = models.ImageField(upload_to='products/product/') category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='products') price = models.PositiveBigIntegerField() description = models.TextField(null=True, blank=True) + unity = models.ForeignKey(Unity, on_delete=models.CASCADE, related_name='products', null=True) def __str__(self): return self.name class Meta: verbose_name = 'Mahsulot' - verbose_name_plural = 'Mahsulotlar' - + verbose_name_plural = 'Mahsulotlar' \ No newline at end of file diff --git a/core/apps/products/serializers/product.py b/core/apps/products/serializers/product.py index d1ee021..40c199b 100644 --- a/core/apps/products/serializers/product.py +++ b/core/apps/products/serializers/product.py @@ -6,12 +6,19 @@ from core.apps.accounts.models import Like class ProductListSerializer(serializers.ModelSerializer): liked = serializers.SerializerMethodField(method_name='get_liked') + unity = serializers.SerializerMethodField(method_name='get_unity') class Meta: model = Product fields = [ - 'id', 'name', 'image', 'price', 'description', 'liked' + 'id', 'name', 'image', 'price', 'description', 'liked', 'unity', ] def get_liked(self, obj): - return Like.objects.filter(user=self.context.get('user'), product=obj).exists() \ No newline at end of file + return Like.objects.filter(user=self.context.get('user'), product=obj).exists() + + def get_unity(self, obj): + return { + 'id': obj.unity.id, + 'name': obj.unity.name, + } \ No newline at end of file diff --git a/core/apps/products/urls.py b/core/apps/products/urls.py index 8dc015f..9d455e1 100644 --- a/core/apps/products/urls.py +++ b/core/apps/products/urls.py @@ -14,6 +14,7 @@ urlpatterns = [ [ path('/list/', product_views.ProductListApiView.as_view()), path('list/', product_views.ProductsApiView.as_view()), + path('/', product_views.ProductDetailApiView.as_view()), ] )), path('search/', search_views.SearchApiView.as_view()), diff --git a/core/apps/products/views/product.py b/core/apps/products/views/product.py index e40622d..6d4de0c 100644 --- a/core/apps/products/views/product.py +++ b/core/apps/products/views/product.py @@ -9,12 +9,12 @@ from core.apps.products.serializers import product as serializers class ProductListApiView(generics.GenericAPIView): serializer_class = serializers.ProductListSerializer - queryset = Product.objects.all() + queryset = Product.objects.select_related('unity') permission_classes = [] def get(self, request, category_id): category = get_object_or_404(Category, id=category_id) - products = Product.objects.filter(category=category) + products = Product.objects.filter(category=category).select_related('unity') page = self.paginate_queryset(products) if page is not None: serializer = self.serializer_class(page, many=True, context={'user': request.user}) @@ -25,14 +25,25 @@ class ProductListApiView(generics.GenericAPIView): class ProductsApiView(generics.GenericAPIView): serializer_class = serializers.ProductListSerializer - queryset = Product.objects.all() + queryset = Product.objects.select_related('unity') permission_classes = [] def get(self, request): - products = Product.objects.all() + products = self.queryset page = self.paginate_queryset(products) if page is not None: serializer = self.serializer_class(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.serializer_class(products, many=True) + return Response(serializer.data, status=200) + + +class ProductDetailApiView(generics.GenericAPIView): + serializer_class = serializers.ProductListSerializer + queryset = Product.objects.select_related('unity') + permission_classes = [] + + def get(self, request, id): + product = get_object_or_404(Product, id=id) + serializer = self.serializer_class(product) return Response(serializer.data, status=200) \ No newline at end of file