added endpoints for back office and refactored a little

This commit is contained in:
Anatoly 2019-11-13 12:07:02 +03:00
parent 94f7bda03a
commit 8cf50ff2cd
7 changed files with 171 additions and 47 deletions

View File

@ -290,6 +290,9 @@ class NewsBackOfficeGallerySerializer(serializers.ModelSerializer):
news = news_qs.first()
image = image_qs.first()
if image in news.gallery.all():
raise serializers.ValidationError({'detail': _('Image is already added.')})
attrs['news'] = news
attrs['image'] = image

View File

@ -9,6 +9,7 @@ from gallery.tasks import delete_image
from news import filters, models, serializers
from rating.tasks import add_rating
from utils.permissions import IsCountryAdmin, IsContentPageManager
from utils.views import CreateDestroyGalleryViewMixin
class NewsMixinView:
@ -84,8 +85,7 @@ class NewsBackOfficeLCView(NewsBackOfficeMixinView,
class NewsBackOfficeGalleryCreateDestroyView(NewsBackOfficeMixinView,
generics.CreateAPIView,
generics.DestroyAPIView):
CreateDestroyGalleryViewMixin):
"""Resource for a create gallery for news for back-office users."""
serializer_class = serializers.NewsBackOfficeGallerySerializer
@ -103,24 +103,6 @@ class NewsBackOfficeGalleryCreateDestroyView(NewsBackOfficeMixinView,
return gallery
def create(self, request, *args, **kwargs):
"""Overridden create method"""
super().create(request, *args, **kwargs)
return Response(status=status.HTTP_201_CREATED)
def destroy(self, request, *args, **kwargs):
"""Override destroy method."""
gallery_obj = self.get_object()
if settings.USE_CELERY:
on_commit(lambda: delete_image.delay(image_id=gallery_obj.image.id,
completely=False))
else:
on_commit(lambda: delete_image(image_id=gallery_obj.image.id,
completely=False))
# Delete an instances of NewsGallery model
gallery_obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
class NewsBackOfficeGalleryListView(NewsBackOfficeMixinView, generics.ListAPIView):
"""Resource for returning gallery for news for back-office users."""

View File

@ -2,9 +2,10 @@
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from product import models
from product.serializers import ProductDetailSerializer
from gallery.models import Image
from product import models
from product.serializers import ProductDetailSerializer, ProductTypeBaseSerializer
from tag.models import TagCategory
class ProductBackOfficeGallerySerializer(serializers.ModelSerializer):
@ -33,12 +34,16 @@ class ProductBackOfficeGallerySerializer(serializers.ModelSerializer):
if not product_qs.exists():
raise serializers.ValidationError({'detail': _('Product not found')})
if not image_qs.exists():
raise serializers.ValidationError({'detail': _('Image not found')})
product = product_qs.first()
image = image_qs.first()
if image in product.gallery.all():
raise serializers.ValidationError({'detail': _('Image is already added.')})
attrs['product'] = product
attrs['image'] = image
@ -46,8 +51,10 @@ class ProductBackOfficeGallerySerializer(serializers.ModelSerializer):
class ProductBackOfficeDetailSerializer(ProductDetailSerializer):
"""Product back-office detail serializer."""
class Meta(ProductDetailSerializer.Meta):
"""Meta class."""
fields = ProductDetailSerializer.Meta.fields + [
'description',
'available',
@ -68,3 +75,58 @@ class ProductBackOfficeDetailSerializer(ProductDetailSerializer):
'wine_village': {'write_only': True},
'state': {'write_only': True},
}
class ProductTypeBackOfficeDetailSerializer(ProductTypeBaseSerializer):
"""Product type back-office detail serializer."""
class Meta(ProductTypeBaseSerializer.Meta):
"""Meta class."""
fields = ProductTypeBaseSerializer.Meta.fields + [
'name',
'index_name',
'use_subtypes',
]
extra_kwargs = {
'name': {'write_only': True},
'index_name': {'write_only': True},
'use_subtypes': {'write_only': True},
}
class ProductTypeTagCategorySerializer(serializers.ModelSerializer):
"""Serializer for attaching tag category to product type."""
product_type_id = serializers.PrimaryKeyRelatedField(
queryset=models.ProductType.objects.all(),
write_only=True)
tag_category_id = serializers.PrimaryKeyRelatedField(
queryset=TagCategory.objects.all(),
write_only=True)
class Meta(ProductTypeBaseSerializer.Meta):
"""Meta class."""
fields = ProductTypeBaseSerializer.Meta.fields + [
'product_type_id',
'tag_category_id',
]
def validate(self, attrs):
"""Validation method."""
product_type = attrs.pop('product_type_id')
tag_category = attrs.get('tag_category_id')
if tag_category in product_type.tag_categories.all():
raise serializers.ValidationError({
'detail': _('Tag category is already attached.')})
attrs['product_type'] = product_type
attrs['tag_category'] = tag_category
return attrs
def create(self, validated_data):
"""Overridden create method."""
product_type = validated_data.get('product_type')
tag_category = validated_data.get('tag_category')
product_type.tag_categories.add(tag_category)
return product_type

View File

@ -32,7 +32,8 @@ class ProductSubTypeBaseSerializer(serializers.ModelSerializer):
class ProductTypeBaseSerializer(serializers.ModelSerializer):
"""ProductType base serializer"""
name_translated = TranslatedField()
index_name_display = serializers.CharField(source='get_index_name_display')
index_name_display = serializers.CharField(source='get_index_name_display',
read_only=True)
class Meta:
model = models.ProductType

View File

@ -1,14 +1,27 @@
"""Product backoffice url patterns."""
from django.urls import path
from product.urls.common import urlpatterns as common_urlpatterns
from product import views
urlpatterns = [
path('', views.ProductListCreateBackOfficeView.as_view(), name='list-create'),
path('<int:pk>/', views.ProductDetailBackOfficeView.as_view(), name='rud'),
path('<int:pk>/gallery/', views.ProductBackOfficeGalleryListView.as_view(),
name='gallery-list'),
path('<int:pk>/gallery/<int:image_id>/', views.ProductBackOfficeGalleryCreateDestroyView.as_view(),
name='gallery-create-destroy'),
]
# product types
path('types/', views.ProductTypeListCreateBackOfficeView.as_view(), name='type-list-create'),
path('types/<int:pk>/', views.ProductTypeRUDBackOfficeView.as_view(),
name='type-retrieve-update-destroy'),
path('types/attach-tag-category/', views.ProductTypeTagCategoryCreateBackOfficeView.as_view(),
name='type-tag-category-create'),
# product sub types
# path('subtypes/', views.ProductSubTypeListCreateBackOfficeView.as_view(),
# name='subtype-list-create'),
# path('subtypes/<int:pk>/', views.ProductSubTypeRUDBackOfficeView.as_view(),
# name='subtype-retrieve-update-destroy'),
# path('subtypes/attach-tag-category/', views.ProductSubTypeTagCategoryCreateBackOfficeView.as_view(),
# name='subtype-tag-category-create'),
urlpatterns.extend(common_urlpatterns)
]

View File

@ -2,11 +2,12 @@
from django.conf import settings
from django.db.transaction import on_commit
from django.shortcuts import get_object_or_404
from rest_framework import generics, status, permissions
from rest_framework import generics, status, permissions, views
from rest_framework.response import Response
from gallery.tasks import delete_image
from product import serializers, models
from utils.views import CreateDestroyGalleryViewMixin
class ProductBackOfficeMixinView:
@ -17,9 +18,34 @@ class ProductBackOfficeMixinView:
.order_by('-created', )
class ProductTypeBackOfficeMixinView:
"""Product type back-office mixin view."""
permission_classes = (permissions.IsAuthenticated,)
queryset = models.ProductType.objects.all()
class ProductSubTypeBackOfficeMixinView:
"""Product sub type back-office mixin view."""
permission_classes = (permissions.IsAuthenticated,)
queryset = models.ProductSubType.objects.all()
class BackOfficeListCreateMixin(views.APIView):
"""Back-office list-create mixin view."""
def check_permissions(self, request):
"""
Check if the request should be permitted.
Raises an appropriate exception if the request is not permitted.
"""
if self.request.method != 'GET':
super().check_permissions(request)
class ProductBackOfficeGalleryCreateDestroyView(ProductBackOfficeMixinView,
generics.CreateAPIView,
generics.DestroyAPIView):
CreateDestroyGalleryViewMixin):
"""Resource for a create gallery for product for back-office users."""
serializer_class = serializers.ProductBackOfficeGallerySerializer
@ -37,24 +63,6 @@ class ProductBackOfficeGalleryCreateDestroyView(ProductBackOfficeMixinView,
return gallery
def create(self, request, *args, **kwargs):
"""Overridden create method"""
super().create(request, *args, **kwargs)
return Response(status=status.HTTP_201_CREATED)
def destroy(self, request, *args, **kwargs):
"""Override destroy method."""
gallery_obj = self.get_object()
if settings.USE_CELERY:
on_commit(lambda: delete_image.delay(image_id=gallery_obj.image.id,
completely=False))
else:
on_commit(lambda: delete_image(image_id=gallery_obj.image.id,
completely=False))
# Delete an instances of ProductGallery model
gallery_obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
class ProductBackOfficeGalleryListView(ProductBackOfficeMixinView, generics.ListAPIView):
"""Resource for returning gallery for product for back-office users."""
@ -78,3 +86,32 @@ class ProductBackOfficeGalleryListView(ProductBackOfficeMixinView, generics.List
class ProductDetailBackOfficeView(ProductBackOfficeMixinView, generics.RetrieveUpdateDestroyAPIView):
"""Product back-office R/U/D view."""
serializer_class = serializers.ProductBackOfficeDetailSerializer
class ProductListCreateBackOfficeView(BackOfficeListCreateMixin, ProductBackOfficeMixinView,
generics.ListCreateAPIView):
"""Product back-office list-create view."""
serializer_class = serializers.ProductBackOfficeDetailSerializer
class ProductTypeListCreateBackOfficeView(BackOfficeListCreateMixin, ProductTypeBackOfficeMixinView,
generics.ListCreateAPIView):
"""Product type back-office list-create view."""
serializer_class = serializers.ProductTypeBackOfficeDetailSerializer
class ProductTypeRUDBackOfficeView(BackOfficeListCreateMixin, ProductTypeBackOfficeMixinView,
generics.RetrieveUpdateDestroyAPIView):
"""Product type back-office retrieve-update-destroy view."""
serializer_class = serializers.ProductTypeBackOfficeDetailSerializer
class ProductTypeTagCategoryCreateBackOfficeView(ProductTypeBackOfficeMixinView,
generics.CreateAPIView):
"""View for attaching tag category to product type."""
serializer_class = serializers.ProductTypeTagCategorySerializer
def create(self, request, *args, **kwargs):
super().create(request, *args, **kwargs)
return Response(status=status.HTTP_201_CREATED)

View File

@ -1,10 +1,13 @@
from collections import namedtuple
from django.conf import settings
from django.db.transaction import on_commit
from rest_framework import generics
from rest_framework import status
from rest_framework.response import Response
from gallery.tasks import delete_image
# JWT
# Login base view mixins
@ -95,3 +98,26 @@ class JWTGenericViewMixin(generics.GenericAPIView):
http_only=self.REFRESH_TOKEN_HTTP_ONLY,
secure=self.REFRESH_TOKEN_SECURE,
max_age=_cookies.get('max_age'))]
class CreateDestroyGalleryViewMixin(generics.CreateAPIView,
generics.DestroyAPIView):
"""Mixin for creating and destroying entity linked with gallery."""
def create(self, request, *args, **kwargs):
"""Overridden create method"""
super().create(request, *args, **kwargs)
return Response(status=status.HTTP_201_CREATED)
def destroy(self, request, *args, **kwargs):
"""Override destroy method."""
gallery_obj = self.get_object()
if settings.USE_CELERY:
on_commit(lambda: delete_image.delay(image_id=gallery_obj.image.id,
completely=False))
else:
on_commit(lambda: delete_image(image_id=gallery_obj.image.id,
completely=False))
# Delete an instances of Gallery model
gallery_obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)