161 lines
6.7 KiB
YAML
161 lines
6.7 KiB
YAML
apiVersion: v1
|
||
data:
|
||
asset.py: |
|
||
from typing import List
|
||
|
||
from django.conf import settings
|
||
from django.http import HttpResponseBadRequest
|
||
from django_filters import rest_framework as django_filters
|
||
from rest_framework import status
|
||
from rest_framework.decorators import action
|
||
from rest_framework.response import Response
|
||
from rest_framework import filters
|
||
|
||
from rest_framework.viewsets import ModelViewSet
|
||
|
||
from assets.api.v0.filters.asset import AssetFilter
|
||
from assets.models import Asset
|
||
from assets.serializers import (
|
||
AssetSerializer,
|
||
AssetSearchSerializer,
|
||
# AssetCopySerializer,
|
||
AssetCopyRequestSerializer,
|
||
)
|
||
from core.permissions import CompanyIdTokenBasedPermission
|
||
|
||
|
||
class AssetViewSet(ModelViewSet):
|
||
|
||
queryset = Asset.objects.all()
|
||
|
||
filterset_class = AssetFilter
|
||
filter_backends = (django_filters.DjangoFilterBackend, filters.OrderingFilter, )
|
||
|
||
serializer_class = AssetSerializer
|
||
topic = settings.ASSETS_TOPIC
|
||
permission_classes = [CompanyIdTokenBasedPermission, ]
|
||
|
||
ordering_fields = ['created_at', 'name']
|
||
ordering = ['-created_at']
|
||
|
||
def get_queryset(self):
|
||
validated_token = self.request.auth
|
||
print(self.request.auth)
|
||
#user_company_ids = validated_token.get("company_ids")
|
||
is_superuser = True
|
||
if is_superuser:
|
||
return Asset.objects.all()
|
||
return Asset.objects.filter(
|
||
tenant_id__in=1,
|
||
)
|
||
|
||
def get_serializer(self, *args, **kwargs):
|
||
if isinstance(kwargs.get("data", {}), list):
|
||
kwargs["many"] = True
|
||
return super().get_serializer(*args, **kwargs)
|
||
|
||
def list_update(self, request, *args, **kwargs):
|
||
instances = self.get_queryset().filter(id__in=[item.get('id') for item in request.data])
|
||
serializer = self.serializer_class(instances, data=request.data, many=True)
|
||
serializer.is_valid(raise_exception=True)
|
||
serializer.save()
|
||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||
|
||
def list_partial_update(self, request, *args, **kwargs):
|
||
instances = self.get_queryset().filter(id__in=[item.get('id') for item in request.data])
|
||
serializer = self.serializer_class(instances, data=request.data, many=True, partial=True)
|
||
serializer.is_valid(raise_exception=True)
|
||
serializer.save()
|
||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||
|
||
def destroy(self, request, *args, **kwargs):
|
||
serializer = self.get_serializer()
|
||
parent = self.get_object()
|
||
instances = self.queryset.filter(path__icontains=parent.id)
|
||
for i in instances:
|
||
serializer.destroy(i)
|
||
return Response(None, status=status.HTTP_200_OK)
|
||
|
||
@action(detail=True, methods=['post'])
|
||
def copy(self, request, *args, **kwargs):
|
||
serializer = self.get_serializer()
|
||
request_serializer = AssetCopyRequestSerializer(data=request.data)
|
||
source = self.get_object()
|
||
|
||
if source.parent_id:
|
||
return HttpResponseBadRequest("Only root assets are allowed")
|
||
|
||
request_serializer.is_valid(raise_exception=True)
|
||
if request_serializer.validated_data["recursive"]:
|
||
name = request_serializer.validated_data["destination"]["name"] if \
|
||
request_serializer.validated_data["destination"]["name"] else source.name
|
||
destination = self.copy_recursive(source.id, name,
|
||
request_serializer.validated_data["destination"]["resource_id"])
|
||
else:
|
||
destination = serializer.copy(source, request_serializer.validated_data["destination"])
|
||
return Response(AssetSerializer(destination).data, status=status.HTTP_201_CREATED)
|
||
|
||
def copy_recursive(self, root_id: int, root_name: str, resource_id: str) -> Asset:
|
||
root_copy = None
|
||
serializer = self.get_serializer()
|
||
copies_map = {}
|
||
|
||
# Мы должны гарантировать, что дочерние ноды будут созданы в базе не раньше родительских
|
||
sorted_nodes = self.sort_nodes(root_id)
|
||
|
||
for source in sorted_nodes:
|
||
# Установить имя копии как у оригинала, но в случае рута - целевое имя
|
||
if source.parent_id:
|
||
copy_data = {
|
||
"name": source.name,
|
||
"parent_id": copies_map[source.parent_id],
|
||
"resource_id": resource_id
|
||
}
|
||
destination = serializer.copy(source, copy_data)
|
||
else:
|
||
copy_data = {
|
||
"name": root_name,
|
||
"parent_id": None,
|
||
"resource_id": resource_id
|
||
}
|
||
destination = serializer.copy(source, copy_data)
|
||
root_copy = destination
|
||
|
||
copies_map[source.id] = destination.id
|
||
return root_copy
|
||
|
||
def sort_nodes(self, root_id: int) -> List[Asset]:
|
||
nodes_instances = self.queryset.filter(path__icontains=root_id)
|
||
sort_dict = {}
|
||
sorted_nodes = []
|
||
|
||
for node in nodes_instances:
|
||
# Так как копировать можно только руты, уровень вложенности можно посчитать по количеству точек в пути
|
||
node_level = node.path.count('.')
|
||
if node_level not in sort_dict:
|
||
sort_dict[node_level] = []
|
||
sort_dict[node_level].append(node)
|
||
|
||
current_level = 0
|
||
while current_level in sort_dict:
|
||
sorted_nodes.extend(sort_dict[current_level])
|
||
current_level += 1
|
||
|
||
return sorted_nodes
|
||
|
||
@action(detail=False, methods=["POST"])
|
||
def search(self, request, *args, **kwargs):
|
||
request_serializer = AssetSearchSerializer(data=request.data)
|
||
request_serializer.is_valid(raise_exception=True)
|
||
|
||
instances = self.get_queryset()
|
||
if request_serializer.data["id"]:
|
||
instances = instances.filter(id__in=request_serializer.data["id"])
|
||
|
||
serializer = self.serializer_class(instances, many=True)
|
||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||
kind: ConfigMap
|
||
metadata:
|
||
name: asset
|
||
namespace: eav
|