Improve readability by removing unnecessary parentheses in `min_price` and `max_price` methods in `models.py`. Enhance JSON serialization error formatting in `views.py` and adjustment of field formatting in serializers. No functional changes, purely stylistic updates for code maintainability.
437 lines
10 KiB
Python
437 lines
10 KiB
Python
import logging
|
|
from contextlib import suppress
|
|
from typing import Any
|
|
|
|
from drf_spectacular.utils import extend_schema_field
|
|
from rest_framework.fields import DecimalField, JSONField, SerializerMethodField
|
|
from rest_framework.serializers import ListSerializer, ModelSerializer
|
|
from rest_framework_recursive.fields import RecursiveField
|
|
|
|
from engine.core.models import (
|
|
Attribute,
|
|
AttributeGroup,
|
|
AttributeValue,
|
|
Brand,
|
|
Category,
|
|
Feedback,
|
|
Order,
|
|
OrderProduct,
|
|
Product,
|
|
ProductImage,
|
|
ProductTag,
|
|
PromoCode,
|
|
Promotion,
|
|
Stock,
|
|
Vendor,
|
|
Wishlist,
|
|
)
|
|
from engine.core.serializers.simple import (
|
|
BrandSimpleSerializer,
|
|
CategorySimpleSerializer,
|
|
ProductSimpleSerializer,
|
|
)
|
|
from engine.core.serializers.utility import AddressSerializer
|
|
from engine.core.typing import FilterableAttribute
|
|
from engine.core.utils.markdown import render_markdown
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class AttributeGroupDetailSerializer(ModelSerializer):
|
|
children = RecursiveField(many=True)
|
|
|
|
class Meta:
|
|
model = AttributeGroup
|
|
fields = [
|
|
"uuid",
|
|
"name",
|
|
"children",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
|
|
class CategoryDetailListSerializer(ListSerializer):
|
|
def to_representation(self, data):
|
|
items = list(data)
|
|
with suppress(Exception):
|
|
Category.bulk_prefetch_filterable_attributes(items)
|
|
return super().to_representation(items)
|
|
|
|
|
|
class CategoryDetailSerializer(ModelSerializer):
|
|
children = SerializerMethodField()
|
|
description = SerializerMethodField()
|
|
filterable_attributes = SerializerMethodField()
|
|
brands = BrandSimpleSerializer(many=True, read_only=True)
|
|
min_price = DecimalField(
|
|
max_digits=12, decimal_places=2, read_only=True, coerce_to_string=False
|
|
)
|
|
max_price = DecimalField(
|
|
max_digits=12, decimal_places=2, read_only=True, coerce_to_string=False
|
|
)
|
|
|
|
class Meta:
|
|
model = Category
|
|
list_serializer_class = CategoryDetailListSerializer
|
|
fields = [
|
|
"uuid",
|
|
"name",
|
|
"description",
|
|
"image",
|
|
"markup_percent",
|
|
"filterable_attributes",
|
|
"brands",
|
|
"min_price",
|
|
"max_price",
|
|
"children",
|
|
"slug",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
def get_description(self, obj: Category) -> str:
|
|
return render_markdown(obj.description or "")
|
|
|
|
def get_filterable_attributes(self, obj: Category) -> list[FilterableAttribute]:
|
|
return obj.filterable_attributes
|
|
|
|
@extend_schema_field(CategorySimpleSerializer(many=True))
|
|
def get_children(self, obj: Category) -> list[dict[str, Any]]:
|
|
request = self.context.get("request")
|
|
if request is not None and request.user.has_perm("view_category"):
|
|
children = obj.children.all()
|
|
else:
|
|
children = obj.children.filter(is_active=True)
|
|
|
|
if obj.children.exists():
|
|
serializer = CategorySimpleSerializer(
|
|
children, many=True, context=self.context
|
|
)
|
|
return list(serializer.data)
|
|
return []
|
|
|
|
|
|
class BrandDetailSerializer(ModelSerializer):
|
|
categories = CategorySimpleSerializer(many=True)
|
|
description = SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Brand
|
|
fields = [
|
|
"uuid",
|
|
"name",
|
|
"description",
|
|
"categories",
|
|
"created",
|
|
"modified",
|
|
"big_logo",
|
|
"small_logo",
|
|
]
|
|
|
|
def get_description(self, obj: Brand) -> str:
|
|
return render_markdown(obj.description or "")
|
|
|
|
|
|
class BrandProductDetailSerializer(ModelSerializer):
|
|
class Meta:
|
|
model = Brand
|
|
fields = [
|
|
"uuid",
|
|
"name",
|
|
"created",
|
|
"modified",
|
|
"big_logo",
|
|
"small_logo",
|
|
]
|
|
|
|
|
|
class ProductTagDetailSerializer(ModelSerializer):
|
|
class Meta:
|
|
model = ProductTag
|
|
fields = [
|
|
"uuid",
|
|
"tag_name",
|
|
"name",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
|
|
class ProductImageDetailSerializer(ModelSerializer):
|
|
class Meta:
|
|
model = ProductImage
|
|
fields = [
|
|
"uuid",
|
|
"alt",
|
|
"image",
|
|
"priority",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
|
|
class AttributeDetailSerializer(ModelSerializer):
|
|
categories = CategoryDetailSerializer(many=True)
|
|
group = AttributeGroupDetailSerializer()
|
|
|
|
class Meta:
|
|
model = Attribute
|
|
fields = [
|
|
"uuid",
|
|
"name",
|
|
"value_type",
|
|
"categories",
|
|
"group",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
|
|
class AttributeInnerSerializer(ModelSerializer):
|
|
group = AttributeGroupDetailSerializer()
|
|
|
|
class Meta:
|
|
model = Attribute
|
|
fields = [
|
|
"uuid",
|
|
"name",
|
|
"value_type",
|
|
"group",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
|
|
class AttributeValueDetailSerializer(ModelSerializer):
|
|
attribute = AttributeInnerSerializer()
|
|
|
|
class Meta:
|
|
model = AttributeValue
|
|
fields = [
|
|
"uuid",
|
|
"attribute",
|
|
"value",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
|
|
class VendorDetailSerializer(ModelSerializer):
|
|
class Meta:
|
|
model = Vendor
|
|
fields = [
|
|
"uuid",
|
|
"name",
|
|
"authentication",
|
|
"markup_percent",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
|
|
class StockDetailSerializer(ModelSerializer):
|
|
vendor = VendorDetailSerializer()
|
|
|
|
class Meta:
|
|
model = Stock
|
|
fields = [
|
|
"uuid",
|
|
"vendor",
|
|
"price",
|
|
"purchase_price",
|
|
"quantity",
|
|
"sku",
|
|
"digital_asset",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
|
|
class PromoCodeDetailSerializer(ModelSerializer):
|
|
class Meta:
|
|
model = PromoCode
|
|
fields = [
|
|
"uuid",
|
|
"code",
|
|
"discount_amount",
|
|
"discount_percent",
|
|
"start_time",
|
|
"end_time",
|
|
"used_on",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
|
|
class ProductDetailSerializer(ModelSerializer):
|
|
brand = BrandProductDetailSerializer()
|
|
category = CategorySimpleSerializer()
|
|
tags = ProductTagDetailSerializer(
|
|
many=True,
|
|
)
|
|
images = ProductImageDetailSerializer(
|
|
many=True,
|
|
)
|
|
attributes = AttributeValueDetailSerializer(
|
|
many=True,
|
|
)
|
|
|
|
description = SerializerMethodField()
|
|
rating = SerializerMethodField()
|
|
price = DecimalField(
|
|
max_digits=12, decimal_places=2, read_only=True, coerce_to_string=False
|
|
)
|
|
quantity = SerializerMethodField()
|
|
feedbacks_count = SerializerMethodField()
|
|
discount_price = DecimalField(
|
|
max_digits=12,
|
|
decimal_places=2,
|
|
read_only=True,
|
|
allow_null=True,
|
|
coerce_to_string=False,
|
|
)
|
|
personal_orders_only = SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Product
|
|
fields = [
|
|
"uuid",
|
|
"sku",
|
|
"name",
|
|
"description",
|
|
"video",
|
|
"partnumber",
|
|
"is_digital",
|
|
"brand",
|
|
"category",
|
|
"feedbacks_count",
|
|
"quantity",
|
|
"tags",
|
|
"slug",
|
|
"images",
|
|
"attributes",
|
|
"rating",
|
|
"price",
|
|
"created",
|
|
"modified",
|
|
"discount_price",
|
|
"personal_orders_only",
|
|
]
|
|
|
|
def get_description(self, obj: Product) -> str:
|
|
return render_markdown(obj.description or "")
|
|
|
|
def get_rating(self, obj: Product) -> float:
|
|
return obj.rating
|
|
|
|
def get_feedbacks_count(self, obj: Product) -> int:
|
|
return obj.feedbacks_count
|
|
|
|
def get_personal_orders_only(self, obj: Product) -> bool:
|
|
return obj.personal_orders_only
|
|
|
|
def get_quantity(self, obj: Product) -> int:
|
|
return obj.quantity
|
|
|
|
|
|
class PromotionDetailSerializer(ModelSerializer):
|
|
products = ProductDetailSerializer(
|
|
many=True,
|
|
)
|
|
description = SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Promotion
|
|
fields = [
|
|
"uuid",
|
|
"name",
|
|
"discount_percent",
|
|
"description",
|
|
"products",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
def get_description(self, obj: Promotion) -> str:
|
|
return render_markdown(obj.description or "")
|
|
|
|
|
|
class WishlistDetailSerializer(ModelSerializer):
|
|
products = ProductSimpleSerializer(
|
|
many=True,
|
|
)
|
|
|
|
class Meta:
|
|
model = Wishlist
|
|
fields = [
|
|
"uuid",
|
|
"products",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
|
|
class OrderProductDetailSerializer(ModelSerializer):
|
|
product = ProductDetailSerializer()
|
|
billing_address = AddressSerializer(read_only=True, required=False)
|
|
shipping_address = AddressSerializer(read_only=True, required=False)
|
|
attributes = JSONField(required=False)
|
|
|
|
class Meta:
|
|
model = OrderProduct
|
|
fields = [
|
|
"uuid",
|
|
"product",
|
|
"quantity",
|
|
"buy_price",
|
|
"comments",
|
|
"notifications",
|
|
"billing_address",
|
|
"shipping_address",
|
|
"attributes",
|
|
"status",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
|
|
class FeedbackDetailSerializer(ModelSerializer):
|
|
order_product = OrderProductDetailSerializer()
|
|
|
|
class Meta:
|
|
model = Feedback
|
|
fields = [
|
|
"uuid",
|
|
"rating",
|
|
"comment",
|
|
"order_product",
|
|
"created",
|
|
"modified",
|
|
]
|
|
|
|
|
|
class OrderDetailSerializer(ModelSerializer):
|
|
promo_code = PromoCodeDetailSerializer()
|
|
order_products = OrderProductDetailSerializer(
|
|
many=True,
|
|
)
|
|
total_price = DecimalField(
|
|
max_digits=12, decimal_places=2, read_only=True, coerce_to_string=False
|
|
)
|
|
|
|
class Meta:
|
|
model = Order
|
|
fields = [
|
|
"uuid",
|
|
"status",
|
|
"total_price",
|
|
"promo_code",
|
|
"billing_address",
|
|
"shipping_address",
|
|
"buy_time",
|
|
"order_products",
|
|
"human_readable_id",
|
|
"created",
|
|
"modified",
|
|
]
|