categorylanri import qilish qoshildi

This commit is contained in:
Husanjonazamov
2026-03-26 14:06:37 +05:00
parent 00f9e6be54
commit bcea5f4a70
13 changed files with 319 additions and 56 deletions

View File

@@ -8,6 +8,13 @@ from core.apps.vendors.models import CategoryModel
class CategoryAdmin(ModelAdmin):
list_display = (
"id",
"__str__",
"title",
"section",
"photo",
"photo_url",
"is_publish",
"order",
)
search_fields = ("title", "firestore_id")
list_filter = ("section", "is_publish")

View File

@@ -8,13 +8,26 @@ from core.apps.vendors.models import ProductimageModel, VendorproductModel
class VendorproductAdmin(ModelAdmin):
list_display = (
"id",
"__str__",
"name",
"vendor",
"category",
"section",
"price",
"quantity",
"is_publish",
"image",
)
search_fields = ("name", "firestore_id", "vendor")
list_filter = ("is_publish", "category", "section")
autocomplete_fields = ("category", "section")
@admin.register(ProductimageModel)
class ProductimageAdmin(ModelAdmin):
list_display = (
"id",
"__str__",
"product",
"image",
"order",
)
list_filter = ("product",)

View File

@@ -19,23 +19,58 @@ class BaseCategorySerializer(serializers.ModelSerializer):
"is_publish",
"order",
]
def to_representation(self, instance):
ret = super().to_representation(instance)
request = self.context.get("request")
photo_url = ret.get("photo_url")
if photo_url and isinstance(photo_url, str):
if not photo_url.startswith("http"):
path = f"/resources/media/{photo_url.lstrip('/')}"
if request:
ret["photo_url"] = request.build_absolute_uri(path)
else:
ret["photo_url"] = path
elif "localhost" in photo_url and request and "localhost" not in request.get_host():
path = photo_url.split("/resources/media/")[-1]
ret["photo_url"] = request.build_absolute_uri(f"/resources/media/{path}")
# Fallback for main photo if it's null
if not ret.get("photo") and ret.get("photo_url"):
ret["photo"] = ret["photo_url"]
# Ensure main photo is absolute if it's a relative path
photo = ret.get("photo")
if photo and isinstance(photo, str) and not photo.startswith("http"):
if not photo.startswith("/resources/"):
photo = f"/resources/media/{photo.lstrip('/')}"
if request:
ret["photo"] = request.build_absolute_uri(photo)
else:
ret["photo"] = photo
return ret
class ListCategorySerializer(BaseCategorySerializer):
class Meta(BaseCategorySerializer.Meta): ...
class Meta(BaseCategorySerializer.Meta):
pass
class RetrieveCategorySerializer(BaseCategorySerializer):
class Meta(BaseCategorySerializer.Meta): ...
class Meta(BaseCategorySerializer.Meta):
pass
class CreateCategorySerializer(BaseCategorySerializer):
class Meta(BaseCategorySerializer.Meta):
fields = [
"id",
"firestore_id",
"section",
"title",
"description",
"photo",
"photo_url",
"is_publish",
"order",

View File

@@ -15,6 +15,39 @@ class BaseSectionSerializer(serializers.ModelSerializer):
"service_type",
]
def to_representation(self, instance):
ret = super().to_representation(instance)
request = self.context.get("request")
image_url = ret.get("image_url")
if image_url and isinstance(image_url, str):
if not image_url.startswith("http"):
path = f"/resources/media/{image_url.lstrip('/')}"
if request:
ret["image_url"] = request.build_absolute_uri(path)
else:
ret["image_url"] = path
elif "localhost" in image_url and request and "localhost" not in request.get_host():
path = image_url.split("/resources/media/")[-1]
ret["image_url"] = request.build_absolute_uri(f"/resources/media/{path}")
# Fallback for main image if it's null
if not ret.get("image") and ret.get("image_url"):
ret["image"] = ret["image_url"]
# Ensure main image is absolute if it's a relative path
image = ret.get("image")
if image and isinstance(image, str) and not image.startswith("http"):
if not image.startswith("/resources/"):
image = f"/resources/media/{image.lstrip('/')}"
if request:
ret["image"] = request.build_absolute_uri(image)
else:
ret["image"] = image
return ret
class ListSectionSerializer(BaseSectionSerializer):
pass

View File

@@ -20,25 +20,60 @@ class BaseVendorSerializer(serializers.ModelSerializer):
"photo_url",
"is_active",
]
def to_representation(self, instance):
ret = super().to_representation(instance)
request = self.context.get("request")
photo_url = ret.get("photo_url")
if photo_url and isinstance(photo_url, str):
if not photo_url.startswith("http"):
path = f"/resources/media/{photo_url.lstrip('/')}"
if request:
ret["photo_url"] = request.build_absolute_uri(path)
else:
ret["photo_url"] = path
elif "localhost" in photo_url and request and "localhost" not in request.get_host():
path = photo_url.split("/resources/media/")[-1]
ret["photo_url"] = request.build_absolute_uri(f"/resources/media/{path}")
# Fallback for main photo if it's null
if not ret.get("photo") and ret.get("photo_url"):
ret["photo"] = ret["photo_url"]
# Ensure main photo is absolute if it's a relative path
photo = ret.get("photo")
if photo and isinstance(photo, str) and not photo.startswith("http"):
if not photo.startswith("/resources/"):
photo = f"/resources/media/{photo.lstrip('/')}"
if request:
ret["photo"] = request.build_absolute_uri(photo)
else:
ret["photo"] = photo
return ret
class ListVendorSerializer(BaseVendorSerializer):
class Meta(BaseVendorSerializer.Meta): ...
class Meta(BaseVendorSerializer.Meta):
pass
class RetrieveVendorSerializer(BaseVendorSerializer):
class Meta(BaseVendorSerializer.Meta): ...
class Meta(BaseVendorSerializer.Meta):
pass
class CreateVendorSerializer(BaseVendorSerializer):
class Meta(BaseVendorSerializer.Meta):
fields = [
"id",
"firestore_id",
"section",
"title",
"description",
"phone",
"location",
"photo",
"photo_url",
"is_active",
]

View File

@@ -8,7 +8,9 @@ class BaseProductimageSerializer(serializers.ModelSerializer):
model = ProductimageModel
fields = [
"id",
"name",
"product",
"image",
"order",
]
@@ -23,6 +25,7 @@ class RetrieveProductimageSerializer(BaseProductimageSerializer):
class CreateProductimageSerializer(BaseProductimageSerializer):
class Meta(BaseProductimageSerializer.Meta):
fields = [
"id",
"name",
"product",
"image",
"order",
]

View File

@@ -3,9 +3,13 @@ from rest_framework import serializers
from core.apps.vendors.models import VendorproductModel, VendorModel, CategoryModel, SectionModel
from core.apps.vendors.serializers.vendor_product.ProductImage import ListProductimageSerializer
class BaseVendorproductSerializer(serializers.ModelSerializer):
category = serializers.SlugRelatedField(slug_field='firestore_id', queryset=CategoryModel.objects.all(), required=False, allow_null=True)
section = serializers.SlugRelatedField(slug_field='firestore_id', queryset=SectionModel.objects.all(), required=False, allow_null=True)
images = ListProductimageSerializer(many=True, read_only=True)
class Meta:
model = VendorproductModel
@@ -22,30 +26,106 @@ class BaseVendorproductSerializer(serializers.ModelSerializer):
"quantity",
"is_publish",
"image",
"images",
"photos_json",
]
def to_representation(self, instance):
ret = super().to_representation(instance)
request = self.context.get("request")
photos = ret.get("photos_json")
# Handle photos_json list
processed_photos = []
if photos and isinstance(photos, list):
for photo in photos:
if isinstance(photo, str):
# Agar URL to'liq bo'lmasa yoki localhost bo'lsa, uni dinamik qilamiz
if not photo.startswith("http"):
path = f"/resources/media/{photo}"
if request:
processed_photos.append(request.build_absolute_uri(path))
else:
processed_photos.append(path)
elif "localhost" in photo and request and "localhost" not in request.get_host():
# Agar bazada localhost saqlangan bo'lsa-yu, biz boshqa domenda bo'lsak
path = photo.split("/resources/media/")[-1]
processed_photos.append(request.build_absolute_uri(f"/resources/media/{path}"))
else:
processed_photos.append(photo)
else:
processed_photos.append(photo)
ret["photos_json"] = processed_photos
# Fallback for main image if it's null
if not ret.get("image") and processed_photos:
ret["image"] = processed_photos[0]
# Ensure main image is absolute if it's a relative path (fallback for custom storage)
image = ret.get("image")
if image and isinstance(image, str) and not image.startswith("http"):
# Check if it already has resources prefix
if not image.startswith("/resources/"):
image = f"/resources/media/{image.lstrip('/')}"
if request:
ret["image"] = request.build_absolute_uri(image)
else:
ret["image"] = image
return ret
class ListVendorproductSerializer(BaseVendorproductSerializer):
class Meta(BaseVendorproductSerializer.Meta): ...
class Meta(BaseVendorproductSerializer.Meta):
pass
class RetrieveVendorproductSerializer(BaseVendorproductSerializer):
class Meta(BaseVendorproductSerializer.Meta): ...
class Meta(BaseVendorproductSerializer.Meta):
pass
from core.apps.vendors.models import VendorproductModel, ProductimageModel, VendorModel, CategoryModel, SectionModel
class CreateVendorproductSerializer(BaseVendorproductSerializer):
uploaded_images = serializers.ListField(
child=serializers.ImageField(max_length=1000000, allow_empty_file=False, use_url=False),
write_only=True,
required=False
)
class Meta(BaseVendorproductSerializer.Meta):
fields = [
"firestore_id",
"vendor",
"category",
"section",
"name",
"description",
"price",
"discount_price",
"quantity",
"is_publish",
"photos_json",
fields = BaseVendorproductSerializer.Meta.fields + [
"uploaded_images",
]
def create(self, validated_data):
uploaded_images = validated_data.pop("uploaded_images", [])
instance = super().create(validated_data)
# Save additional gallery images
for i, img in enumerate(uploaded_images):
ProductimageModel.objects.create(
product=instance,
image=img,
order=i
)
return instance
def update(self, instance, validated_data):
uploaded_images = validated_data.pop("uploaded_images", [])
instance = super().update(instance, validated_data)
if uploaded_images:
# Optionally clear existing gallery or append?
# I'll append for now based on user's "how to upload multiple"
for i, img in enumerate(uploaded_images):
ProductimageModel.objects.create(
product=instance,
image=img,
order=instance.images.count() + i
)
return instance

View File

@@ -61,7 +61,7 @@ class VendorproductView(BaseViewSetMixin, ModelViewSet):
@extend_schema(tags=["ProductImage"])
class ProductimageView(BaseViewSetMixin, ReadOnlyModelViewSet):
class ProductimageView(BaseViewSetMixin, ModelViewSet):
queryset = ProductimageModel.objects.all()
serializer_class = ListProductimageSerializer
permission_classes = [AllowAny]