"""Tag views.""" from django.conf import settings from rest_framework import permissions from rest_framework import viewsets, mixins, status, generics from rest_framework.decorators import action from rest_framework.response import Response from tag import filters, models, serializers class ChosenTagsView(generics.ListAPIView, viewsets.GenericViewSet): pagination_class = None permission_classes = (permissions.AllowAny,) serializer_class = serializers.TagBaseSerializer filterset_class = filters.TagsFilterSet queryset = models.Tag.objects.all() def get_queryset(self): result_tags_ids = models.ChosenTagSettings.objects \ .by_country_code(self.request.country_code) \ .values('tag_id') return models.Tag.objects \ .filter(id__in=result_tags_ids) \ .order_by_priority() # User`s views & viewsets class TagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ViewSet for TagCategory model.""" filterset_class = filters.TagCategoryFilterSet pagination_class = None permission_classes = (permissions.AllowAny,) queryset = models.TagCategory.objects.with_tags().with_base_related(). \ distinct() serializer_class = serializers.TagCategoryBaseSerializer # BackOffice user`s views & viewsets class BindObjectMixin: """Bind object mixin.""" def get_serializer_class(self): if self.action == 'bind_object': return self.bind_object_serializer_class return self.serializer_class def perform_binding(self, serializer): raise NotImplemented def perform_unbinding(self, serializer): raise NotImplemented @action(methods=['post', 'delete'], detail=True, url_path='bind-object') def bind_object(self, request, pk=None): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) if request.method == 'POST': self.perform_binding(serializer) return Response(serializer.data, status=status.HTTP_201_CREATED) elif request.method == 'DELETE': self.perform_unbinding(serializer) return Response(status=status.HTTP_204_NO_CONTENT) class TagBackOfficeViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, BindObjectMixin, viewsets.GenericViewSet): """List/create tag view.""" pagination_class = None permission_classes = (permissions.IsAuthenticated,) queryset = models.Tag.objects.all() serializer_class = serializers.TagBackOfficeSerializer bind_object_serializer_class = serializers.TagBindObjectSerializer def perform_binding(self, serializer): data = serializer.validated_data tag = data.pop('tag') obj_type = data.get('type') related_object = data.get('related_object') if obj_type == self.bind_object_serializer_class.ESTABLISHMENT: tag.establishments.add(related_object) elif obj_type == self.bind_object_serializer_class.NEWS: tag.news.add(related_object) def perform_unbinding(self, serializer): data = serializer.validated_data tag = data.pop('tag') obj_type = data.get('type') related_object = data.get('related_object') if obj_type == self.bind_object_serializer_class.ESTABLISHMENT: tag.establishments.remove(related_object) elif obj_type == self.bind_object_serializer_class.NEWS: tag.news.remove(related_object) class TagCategoryBackOfficeViewSet(mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.RetrieveModelMixin, BindObjectMixin, TagCategoryViewSet): """ViewSet for TagCategory model for BackOffice users.""" permission_classes = (permissions.IsAuthenticated,) queryset = TagCategoryViewSet.queryset.with_extended_related() serializer_class = serializers.TagCategoryBackOfficeDetailSerializer bind_object_serializer_class = serializers.TagCategoryBindObjectSerializer def perform_binding(self, serializer): data = serializer.validated_data tag_category = data.pop('tag_category') obj_type = data.get('type') related_object = data.get('related_object') if obj_type == self.bind_object_serializer_class.ESTABLISHMENT_TYPE: tag_category.establishment_types.add(related_object) elif obj_type == self.bind_object_serializer_class.NEWS_TYPE: tag_category.news_types.add(related_object) def perform_unbinding(self, serializer): data = serializer.validated_data tag_category = data.pop('tag_category') obj_type = data.get('type') related_object = data.get('related_object') if obj_type == self.bind_object_serializer_class.ESTABLISHMENT_TYPE: tag_category.establishment_types.remove(related_object) elif obj_type == self.bind_object_serializer_class.NEWS_TYPE: tag_category.news_types.remove(related_object)