Features: 1) Add ProductTagType to GraphQL schema with associated queries and resolvers; 2) Register ProductTagViewSet in API URLs and core router; 3) Implement detailed and simple serializers for ProductTag.

Fixes: 1) Correct `serializer_class` assignments for `ProductImageViewSet`, `PromoCodeViewSet`, `PromotionViewSet`, `StockViewSet`, and `WishlistViewSet`.

Extra: 1) General code cleanup and reorganization for viewsets.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-05-29 18:22:44 +03:00
parent 7e40596cb3
commit baf165ddd7
4 changed files with 42 additions and 15 deletions

View file

@ -20,6 +20,7 @@ from core.viewsets import (
CategoryViewSet, CategoryViewSet,
FeedbackViewSet, FeedbackViewSet,
OrderViewSet, OrderViewSet,
ProductTagViewSet,
ProductViewSet, ProductViewSet,
PromoCodeViewSet, PromoCodeViewSet,
PromotionViewSet, PromotionViewSet,
@ -41,6 +42,7 @@ core_router.register(r"stocks", StockViewSet, basename="stocks")
core_router.register(r"promo_codes", PromoCodeViewSet, basename="promo_codes") core_router.register(r"promo_codes", PromoCodeViewSet, basename="promo_codes")
core_router.register(r"promotions", PromotionViewSet, basename="promotions") core_router.register(r"promotions", PromotionViewSet, basename="promotions")
core_router.register(r"addresses", AddressViewSet, basename="addresses") core_router.register(r"addresses", AddressViewSet, basename="addresses")
core_router.register(r"product_tags", ProductTagViewSet, basename="product_tags")
sitemaps = { sitemaps = {
"products": ProductSitemap, "products": ProductSitemap,

View file

@ -21,6 +21,7 @@ from core.models import (
OrderProduct, OrderProduct,
Product, Product,
ProductImage, ProductImage,
ProductTag,
PromoCode, PromoCode,
Promotion, Promotion,
Stock, Stock,
@ -455,6 +456,16 @@ class WishlistType(DjangoObjectType):
description = _("wishlists") description = _("wishlists")
class ProductTagType(DjangoObjectType):
product_set = DjangoFilterConnectionField(ProductType, description=_("tagged products"))
class Meta:
model = ProductTag
interfaces = (relay.Node,)
fields = ("uuid", "tag_name", "name", "product_set")
description = _("product tags")
class ConfigType(ObjectType): class ConfigType(ObjectType):
project_name = String(description=_("project name")) project_name = String(description=_("project name"))
base_domain = String(description=_("company email")) base_domain = String(description=_("company email"))

View file

@ -48,6 +48,7 @@ from core.graphene.object_types import (
OrderProductType, OrderProductType,
OrderType, OrderType,
ProductImageType, ProductImageType,
ProductTagType,
ProductType, ProductType,
PromoCodeType, PromoCodeType,
PromotionType, PromotionType,
@ -64,6 +65,7 @@ from core.models import (
OrderProduct, OrderProduct,
Product, Product,
ProductImage, ProductImage,
ProductTag,
PromoCode, PromoCode,
Promotion, Promotion,
Stock, Stock,
@ -108,6 +110,7 @@ class Query(ObjectType):
product_images = DjangoFilterConnectionField(ProductImageType) product_images = DjangoFilterConnectionField(ProductImageType)
stocks = DjangoFilterConnectionField(StockType) stocks = DjangoFilterConnectionField(StockType)
wishlists = DjangoFilterConnectionField(WishlistType, filterset_class=WishlistFilter) wishlists = DjangoFilterConnectionField(WishlistType, filterset_class=WishlistFilter)
product_tags = DjangoFilterConnectionField(ProductTagType)
promotions = DjangoFilterConnectionField(PromotionType) promotions = DjangoFilterConnectionField(PromotionType)
promocodes = DjangoFilterConnectionField(PromoCodeType) promocodes = DjangoFilterConnectionField(PromoCodeType)
brands = DjangoFilterConnectionField(BrandType, filterset_class=BrandFilter) brands = DjangoFilterConnectionField(BrandType, filterset_class=BrandFilter)
@ -280,6 +283,12 @@ class Query(ObjectType):
return promocodes.filter(user__uuid=kwargs.get("user_uuid")) or promocodes.all() return promocodes.filter(user__uuid=kwargs.get("user_uuid")) or promocodes.all()
return promocodes.filter(is_active=True, user=info.context.user) return promocodes.filter(is_active=True, user=info.context.user)
@staticmethod
def resolve_product_tags(_parent, info, **kwargs):
if info.context.user.has_perm("core.view_producttag"):
return ProductTag.objects.all()
return ProductTag.objects.filter(is_active=True)
class Mutation(ObjectType): class Mutation(ObjectType):
search = Search.Field() search = Search.Field()

View file

@ -73,13 +73,18 @@ from core.serializers import (
OrderProductSimpleSerializer, OrderProductSimpleSerializer,
OrderSimpleSerializer, OrderSimpleSerializer,
ProductDetailSerializer, ProductDetailSerializer,
ProductImageDetailSerializer,
ProductImageSimpleSerializer, ProductImageSimpleSerializer,
ProductSimpleSerializer, ProductSimpleSerializer,
ProductTagDetailSerializer,
ProductTagSimpleSerializer, ProductTagSimpleSerializer,
PromoCodeDetailSerializer,
PromoCodeSimpleSerializer, PromoCodeSimpleSerializer,
PromotionDetailSerializer,
PromotionSimpleSerializer, PromotionSimpleSerializer,
RemoveOrderProductSerializer, RemoveOrderProductSerializer,
RemoveWishlistProductSerializer, RemoveWishlistProductSerializer,
StockDetailSerializer,
StockSimpleSerializer, StockSimpleSerializer,
VendorSimpleSerializer, VendorSimpleSerializer,
WishlistDetailSerializer, WishlistDetailSerializer,
@ -364,21 +369,11 @@ class OrderProductViewSet(EvibesViewSet):
} }
class ProductTagViewSet(EvibesViewSet):
queryset = ProductTag.objects.all()
filter_backends = [DjangoFilterBackend]
filterset_fields = ["tag_name", "is_active"]
serializer_class = AttributeGroupDetailSerializer
action_serializer_classes = {
"list": ProductTagSimpleSerializer,
}
class ProductImageViewSet(EvibesViewSet): class ProductImageViewSet(EvibesViewSet):
queryset = ProductImage.objects.all() queryset = ProductImage.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["product", "priority", "is_active"] filterset_fields = ["product", "priority", "is_active"]
serializer_class = AttributeGroupDetailSerializer serializer_class = ProductImageDetailSerializer
action_serializer_classes = { action_serializer_classes = {
"list": ProductImageSimpleSerializer, "list": ProductImageSimpleSerializer,
} }
@ -388,7 +383,7 @@ class PromoCodeViewSet(EvibesViewSet):
queryset = PromoCode.objects.all() queryset = PromoCode.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["code", "discount_amount", "discount_percent", "start_time", "end_time", "used_on", "is_active"] filterset_fields = ["code", "discount_amount", "discount_percent", "start_time", "end_time", "used_on", "is_active"]
serializer_class = AttributeGroupDetailSerializer serializer_class = PromoCodeDetailSerializer
action_serializer_classes = { action_serializer_classes = {
"list": PromoCodeSimpleSerializer, "list": PromoCodeSimpleSerializer,
} }
@ -398,7 +393,7 @@ class PromotionViewSet(EvibesViewSet):
queryset = Promotion.objects.all() queryset = Promotion.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["name", "discount_percent", "is_active"] filterset_fields = ["name", "discount_percent", "is_active"]
serializer_class = AttributeGroupDetailSerializer serializer_class = PromotionDetailSerializer
action_serializer_classes = { action_serializer_classes = {
"list": PromotionSimpleSerializer, "list": PromotionSimpleSerializer,
} }
@ -408,7 +403,7 @@ class StockViewSet(EvibesViewSet):
queryset = Stock.objects.all() queryset = Stock.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["vendor", "product", "sku", "is_active"] filterset_fields = ["vendor", "product", "sku", "is_active"]
serializer_class = AttributeGroupDetailSerializer serializer_class = StockDetailSerializer
action_serializer_classes = { action_serializer_classes = {
"list": StockSimpleSerializer, "list": StockSimpleSerializer,
} }
@ -419,7 +414,7 @@ class WishlistViewSet(EvibesViewSet):
queryset = Wishlist.objects.all() queryset = Wishlist.objects.all()
filter_backends = [DjangoFilterBackend] filter_backends = [DjangoFilterBackend]
filterset_fields = ["user", "is_active"] filterset_fields = ["user", "is_active"]
serializer_class = AttributeGroupDetailSerializer serializer_class = WishlistDetailSerializer
action_serializer_classes = { action_serializer_classes = {
"list": WishlistSimpleSerializer, "list": WishlistSimpleSerializer,
} }
@ -535,3 +530,13 @@ class AddressViewSet(EvibesViewSet):
) )
return Response(suggestions, status=status.HTTP_200_OK) return Response(suggestions, status=status.HTTP_200_OK)
class ProductTagViewSet(EvibesViewSet):
queryset = ProductTag.objects.all()
filter_backends = [DjangoFilterBackend]
filterset_fields = ["tag_name", "is_active"]
serializer_class = ProductTagDetailSerializer
action_serializer_classes = {
"list": ProductTagSimpleSerializer,
}