more abstract import/export interface

This commit is contained in:
vabene1111
2021-02-08 11:18:13 +01:00
parent f312631676
commit de19a10cba
2 changed files with 59 additions and 63 deletions

View File

@@ -1,14 +1,7 @@
import json import json
import os from io import BytesIO
import uuid
from io import StringIO, BytesIO
from os.path import basename
from zipfile import ZipFile from zipfile import ZipFile
from PIL import Image
from django.core.files import File
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from rest_framework.renderers import JSONRenderer from rest_framework.renderers import JSONRenderer
from cookbook.integration.integration import Integration from cookbook.integration.integration import Integration
@@ -17,51 +10,16 @@ from cookbook.serializer import RecipeExportSerializer
class Default(Integration): class Default(Integration):
def do_export(self, recipes): def get_recipe_from_file(self, file):
export_zip_stream = BytesIO() recipe_zip = ZipFile(file)
export_zip_obj = ZipFile(export_zip_stream, 'w')
for r in recipes:
if r.internal:
recipe_zip_stream = BytesIO()
recipe_zip_obj = ZipFile(recipe_zip_stream, 'w')
recipe_json_stream = StringIO()
recipe_json_stream.write(self.get_export(r))
recipe_zip_obj.writestr('recipe.json', recipe_json_stream.getvalue())
recipe_json_stream.close()
try:
recipe_zip_obj.write(r.image.path, 'image.png')
except ValueError:
pass
recipe_zip_obj.close()
export_zip_obj.writestr(str(r.pk) + '.zip', recipe_zip_stream.getvalue())
export_zip_obj.close()
response = HttpResponse(export_zip_stream.getvalue(), content_type='application/force-download')
response['Content-Disposition'] = 'attachment; filename="export.zip"'
return response
def do_import(self, files):
for f in files:
zip = ZipFile(f.file)
for z in zip.namelist():
self.get_recipe_from_zip(ZipFile(BytesIO(zip.read(z))))
return HttpResponseRedirect(reverse('view_search') + '?keywords=' + str(self.keyword.pk))
def get_recipe_from_zip(self, recipe_zip):
recipe_string = recipe_zip.read('recipe.json').decode("utf-8") recipe_string = recipe_zip.read('recipe.json').decode("utf-8")
recipe = self.get_recipe(recipe_string) recipe = self.decode_recipe(recipe_string)
if 'image.png' in recipe_zip.namelist(): if 'image.png' in recipe_zip.namelist():
recipe.image = File(BytesIO(recipe_zip.read('image.png')), name=f'{uuid.uuid4()}_{recipe.pk}.png') self.import_recipe_image(recipe, BytesIO(recipe_zip.read('image.png')))
recipe.save() return recipe
recipe.keywords.add(self.keyword)
def get_recipe(self, string): def decode_recipe(self, string):
data = json.loads(string) data = json.loads(string)
serialized_recipe = RecipeExportSerializer(data=data, context={'request': self.request}) serialized_recipe = RecipeExportSerializer(data=data, context={'request': self.request})
if serialized_recipe.is_valid(): if serialized_recipe.is_valid():
@@ -70,7 +28,7 @@ class Default(Integration):
return None return None
def get_export(self, recipe): def get_file_from_recipe(self, recipe):
export = RecipeExportSerializer(recipe).data export = RecipeExportSerializer(recipe).data
return JSONRenderer().render(export).decode("utf-8") return 'recipe.json', JSONRenderer().render(export).decode("utf-8")

View File

@@ -1,4 +1,12 @@
import datetime import datetime
import uuid
from io import BytesIO, StringIO
from zipfile import ZipFile
from django.core.files import File
from django.http import HttpResponseRedirect, HttpResponse
from django.urls import reverse
from cookbook.models import Keyword from cookbook.models import Keyword
@@ -16,20 +24,50 @@ class Integration:
) )
def do_export(self, recipes): def do_export(self, recipes):
raise Exception('Method not implemented in storage integration') export_zip_stream = BytesIO()
export_zip_obj = ZipFile(export_zip_stream, 'w')
for r in recipes:
if r.internal:
recipe_zip_stream = BytesIO()
recipe_zip_obj = ZipFile(recipe_zip_stream, 'w')
recipe_stream = StringIO()
filename, data = self.get_file_from_recipe(r)
recipe_stream.write(data)
recipe_zip_obj.writestr(filename, recipe_stream.getvalue())
recipe_stream.close()
try:
recipe_zip_obj.write(r.image.path, 'image.png')
except ValueError:
pass
recipe_zip_obj.close()
export_zip_obj.writestr(str(r.pk) + '.zip', recipe_zip_stream.getvalue())
export_zip_obj.close()
response = HttpResponse(export_zip_stream.getvalue(), content_type='application/force-download')
response['Content-Disposition'] = 'attachment; filename="export.zip"'
return response
def do_import(self, files): def do_import(self, files):
for f in files:
import_zip = ZipFile(f.file)
for z in import_zip.namelist():
recipe = self.get_recipe_from_file(BytesIO(import_zip.read(z)))
recipe.keywords.add(self.keyword)
return HttpResponseRedirect(reverse('view_search') + '?keywords=' + str(self.keyword.pk))
@staticmethod
def import_recipe_image(recipe, image_file):
recipe.image = File(image_file, name=f'{uuid.uuid4()}_{recipe.pk}.png')
recipe.save()
def get_recipe_from_file(self, file):
raise Exception('Method not implemented in storage integration') raise Exception('Method not implemented in storage integration')
def get_recipe(self, string): def get_file_from_recipe(self, recipe):
raise Exception('Method not implemented in storage integration') raise Exception('Method not implemented in storage integration')
def get_export(self, recipe):
raise Exception('Method not implemented in storage integration')
def get_export_file(self, recipe):
try:
with open(recipe.image.path, 'rb') as img_f:
return img_f
except:
return None