""" Views relating to importing and exporting collection items """ """ from interface.views import EnsembleMixin from library.views import WorkMixin from django.views.generic import View from django.http import JsonResponse from djantic import ModelSchema from library.models import Work, Document, Section class DocumentSchema(ModelSchema): class Config: model = Document class WorkSchema(ModelSchema): docs: DocumentSchema class Config: model = Work exclude = ['licence'] class WorkExportView(EnsembleMixin, WorkMixin, View): def get(self, request, *args, **kwargs): obj = self.get_queryset().get(pk=kwargs['pk']) schema = WorkSchema.from_orm(obj) return JsonResponse(schema.dict()) """ from interface.views import AuthorizedResourceMixin from rest_framework import routers, serializers, viewsets from library.models import Collection, Work, Document, Section, WorkMeta import requests from io import BytesIO import tempfile import shutil from django.db import transaction from django.core.files.uploadedfile import TemporaryUploadedFile class WorkMetaSerializer(serializers.ModelSerializer): class Meta: model = WorkMeta exclude = ['id', 'work'] def to_representation(self, instance): return f"{instance.name}:{instance.value}" def to_internal_value(self, data): name, _, value = data.partition(':') return super().to_internal_value({'name': name, 'value': value}) class SectionSerializer(serializers.ModelSerializer): class Meta: model = Section exclude = ['id', 'doc'] def to_representation(self, instance): start = instance.start or 0 end = instance.end or 0 return f"{instance.tag}:{start}:{end}" def to_internal_value(self, data): tag, section_type, start, end = data.split(":") try: start = int(start) except: start = 0 try: end = int(end) except: end = 0 return super().to_internal_value({'tag': tag, 'start': start, 'end': end}) class DocumentSerializer(serializers.ModelSerializer): upload = serializers.URLField() sections = SectionSerializer(many=True) #doctype = serializers.CharField(source='get_doctype_display') #def to_internal_value(self, data): # r = requests.get(data['upload'], stream=True) # with tempfile.NamedTemporaryFile('wb') as f: # shutil.copyfileobj(r.raw, f) # data['upload'] = f.name # print(repr(data)) # return super().to_internal_value(data) def to_representation(self, instance): data = super().to_representation(instance) if data['upload'][0] == '/': data['upload'] = 'http://localhost:8000' + (data['upload']) return data def create(self, validated_data): print("CREATE", validated_data) return super().create(validated_data) def validate(self, data): print("VALIDATE", data) return super().validate(data) def validate_upload(self, value): print("VALIDATE", value) return value class Meta: model = Document exclude = ["id", "work", "version", "created"] # Serializers define the API representation. class WorkSerializer(serializers.ModelSerializer): docs = DocumentSerializer(many=True) meta_info = WorkMetaSerializer(many=True) class Meta: model = Work exclude = ['id', 'collection', 'projects', 'parent'] def create(self, validated): with transaction.atomic(): docs = validated.pop('docs', []) meta = validated.pop('meta_info', []) work = Work.objects.create(**validated) for d in docs: sections = d.pop('sections', []) r = requests.get(d['upload'], stream=True) f = TemporaryUploadedFile(d['upload'], r.headers['content-type'], r.headers['content-length'], r.encoding) shutil.copyfileobj(r.raw, f.file) r.close() d['upload'] = f doc = Document.objects.create(work_id=work.pk, **d) for s in sections: Section.objects.create(doc_id=doc.pk, **s) for m in meta: WorkMeta.objects.create(work_id=work.pk, **m) return work class CollectionSerializer(serializers.Serializer): works = WorkSerializer(many=True) def create(self, validated): s = WorkSerializer() print(validated) collection = validated['collection_id'] with transaction.atomic(): for work in validated['works']: work['collection_id'] = collection s.create(work) return Collection.objects.get(pk=collection) from rest_framework import generics class CollectionExportView(AuthorizedResourceMixin, generics.RetrieveAPIView): serializer_class = CollectionSerializer def get_queryset(self): return Collection.objects.filter(administrators=self.request.user) class WorkExportView(AuthorizedResourceMixin, generics.RetrieveAPIView): serializer_class = WorkSerializer def get_queryset(self): return Work.objects.filter(collection__administrators=self.request.user) class WorkImportView(AuthorizedResourceMixin, generics.CreateAPIView): serializer_class = WorkSerializer def perform_create(self, serializer): serializer.save(collection_id=self.kwargs['pk']) class CollectionImportView(AuthorizedResourceMixin, generics.CreateAPIView): serializer_class = CollectionSerializer def perform_create(self, serializer): serializer.save(collection_id=self.kwargs['pk'])