exporter.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import json
  2. import os
  3. import shutil
  4. from tempfile import TemporaryDirectory
  5. from django.http import FileResponse
  6. from ...core.utils import slugify
  7. def export_theme(theme):
  8. with TemporaryDirectory() as tmp_dir:
  9. export_dir = create_export_directory(tmp_dir, theme)
  10. manifest = create_theme_manifest(theme)
  11. manifest["css"] = write_theme_css(export_dir, theme)
  12. manifest["media"] = write_theme_media(export_dir, theme)
  13. write_theme_manifest(export_dir, manifest)
  14. export_file = zip_theme_export(tmp_dir, export_dir)
  15. export_filename = os.path.split(export_file)[-1]
  16. response = FileResponse(open(export_file, "rb"), content_type="application/zip")
  17. response['Content-Length'] = os.path.getsize(export_file)
  18. response['Content-Disposition'] = "inline; filename=%s" % export_filename
  19. return response
  20. def create_export_directory(tmp_dir, theme):
  21. export_name = get_export_name(theme)
  22. export_dir = os.path.join(tmp_dir, export_name)
  23. os.mkdir(export_dir)
  24. return export_dir
  25. def get_export_name(theme):
  26. if theme.version:
  27. return "%s-%s" % (slugify(theme.name), theme.version.replace(".", "-"))
  28. return slugify(theme.name)
  29. def create_theme_manifest(theme):
  30. return {
  31. "name": theme.name,
  32. "version": theme.version,
  33. "author": theme.author,
  34. "url": theme.url,
  35. "css": [],
  36. "media": [],
  37. }
  38. def write_theme_css(export_dir, theme):
  39. files_dir = create_sub_directory(export_dir, "css")
  40. files = []
  41. for css in theme.css.all():
  42. if css.url:
  43. files.append({
  44. "name": css.name,
  45. "url": css.url,
  46. })
  47. else:
  48. files.append({
  49. "name": css.name,
  50. "path": copy_asset_file(files_dir, css.source_file),
  51. })
  52. return files
  53. def write_theme_media(export_dir, theme):
  54. files_dir = create_sub_directory(export_dir, "media")
  55. files = []
  56. for media in theme.media.all():
  57. files.append({
  58. "name": media.name,
  59. "type": media.type,
  60. "path": copy_asset_file(files_dir, media.file),
  61. })
  62. return files
  63. def create_sub_directory(export_dir, dirname):
  64. new_dir = os.path.join(export_dir, dirname)
  65. os.mkdir(new_dir)
  66. return new_dir
  67. def copy_asset_file(export_dir, asset_file):
  68. filename = os.path.split(asset_file.name)[-1]
  69. dst_path = os.path.join(export_dir, filename)
  70. with open(dst_path, "wb") as fp:
  71. for chunk in asset_file.chunks():
  72. fp.write(chunk)
  73. dirname = os.path.basename(export_dir)
  74. return os.path.join(dirname, filename)
  75. def write_theme_manifest(export_dir, manifest):
  76. manifest_path = os.path.join(export_dir, "manifest.json")
  77. with open(manifest_path, "w") as fp:
  78. json.dump(manifest, fp, ensure_ascii=False, indent=2)
  79. def zip_theme_export(tmp_dir, export_dir):
  80. dir_name = os.path.split(export_dir)[-1]
  81. zip_name = shutil.make_archive(dir_name, 'zip', tmp_dir)
  82. return os.path.join(tmp_dir, zip_name)