157 lines
6.4 KiB
Python
157 lines
6.4 KiB
Python
import json
|
|
import os
|
|
import tempfile
|
|
import zipfile
|
|
|
|
import django
|
|
from django import forms
|
|
from django.conf import settings
|
|
from django.contrib import admin, messages
|
|
from django.contrib.auth import get_permission_codename
|
|
from django.core.exceptions import PermissionDenied
|
|
from django.core.files.storage import default_storage
|
|
from django.http import HttpResponseRedirect
|
|
from django.template.response import TemplateResponse
|
|
from django.urls import path, reverse
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from .. import models
|
|
from .forms import ImportForm
|
|
|
|
|
|
class ImportMixin(admin.ModelAdmin):
|
|
"""
|
|
Import mixin.
|
|
|
|
This is intended to be mixed with django.contrib.admin.ModelAdmin
|
|
https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#modeladmin-objects
|
|
"""
|
|
|
|
#: template for change_list view
|
|
change_list_template = 'admin/import_export/change_list_import.html'
|
|
#: template for import view
|
|
import_template_name = 'admin/import_export/import.html'
|
|
|
|
def get_model_info(self):
|
|
app_label = self.model._meta.app_label
|
|
return (self.model._meta.app_label, self.model._meta.model_name)
|
|
|
|
def has_import_permission(self, request):
|
|
"""
|
|
Returns whether a request has import permission.
|
|
"""
|
|
IMPORT_PERMISSION_CODE = getattr(settings, 'IMPORT_EXPORT_IMPORT_PERMISSION_CODE', None)
|
|
if IMPORT_PERMISSION_CODE is None:
|
|
return True
|
|
|
|
opts = self.opts
|
|
codename = get_permission_codename(IMPORT_PERMISSION_CODE, opts)
|
|
return request.user.has_perm("%s.%s" % (opts.app_label, codename))
|
|
|
|
def get_urls(self):
|
|
urls = super().get_urls()
|
|
info = self.get_model_info()
|
|
my_urls = [
|
|
path('import/',
|
|
self.admin_site.admin_view(self.import_action),
|
|
name='%s_%s_import' % info),
|
|
]
|
|
return my_urls + urls
|
|
|
|
def get_import_context_data(self, **kwargs):
|
|
return self.get_context_data(**kwargs)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
return {}
|
|
|
|
def get_form_kwargs(self, form, *args, **kwargs):
|
|
"""
|
|
Prepare/returns kwargs for the import form.
|
|
|
|
To distinguish between import and confirm import forms,
|
|
the following approach may be used:
|
|
|
|
if isinstance(form, ImportForm):
|
|
# your code here for the import form kwargs
|
|
# e.g. update.kwargs({...})
|
|
elif isinstance(form, ConfirmImportForm):
|
|
# your code here for the confirm import form kwargs
|
|
# e.g. update.kwargs({...})
|
|
...
|
|
"""
|
|
return kwargs
|
|
|
|
def import_action(self, request, *args, **kwargs):
|
|
"""
|
|
Perform a dry_run of the import to make sure the import will not
|
|
result in errors. If there where no error, save the user
|
|
uploaded file to a local temp file that will be used by
|
|
'process_import' for the actual import.
|
|
"""
|
|
if not self.has_import_permission(request):
|
|
raise PermissionDenied
|
|
|
|
context = self.get_import_context_data()
|
|
|
|
form_type = ImportForm
|
|
form_kwargs = self.get_form_kwargs(form_type, *args, **kwargs)
|
|
form = form_type(request.POST or None,
|
|
request.FILES or None,
|
|
**form_kwargs)
|
|
|
|
if request.POST and form.is_valid():
|
|
import_file_tema = form.cleaned_data['tema']
|
|
if zipfile.is_zipfile(import_file_tema):
|
|
with zipfile.ZipFile(import_file_tema, 'r') as zip_ref:
|
|
with tempfile.TemporaryDirectory() as tempdir:
|
|
zip_ref.extractall(tempdir)
|
|
lst = os.listdir(tempdir)
|
|
allowed_extensions=[".gif", ".jpg", ".jpeg", ".png", ".svg"]
|
|
try:
|
|
tema_json = [s for s in os.listdir(f'{tempdir}/{lst[0]}') if '.json' in s][0]
|
|
logo = [s for s in os.listdir(f'{tempdir}/{lst[0]}/logo') if any(ele in s for ele in allowed_extensions)][0]
|
|
favicon = [s for s in os.listdir(f'{tempdir}/{lst[0]}/favicon') if any(ele in s for ele in allowed_extensions)][0]
|
|
with open(f'{tempdir}/{lst[0]}/{tema_json}', 'r') as temporary_file:
|
|
result = json.loads(temporary_file.read())
|
|
with open(f'{tempdir}/{lst[0]}/logo/{logo}', 'rb') as temporary_file:
|
|
default_storage.save(f"admin-interface/logo/{temporary_file.name.split('/')[-1]}", temporary_file)
|
|
with open(f'{tempdir}/{lst[0]}/favicon/{favicon}', 'rb') as temporary_file:
|
|
default_storage.save(f"admin-interface/favicon/{temporary_file.name.split('/')[-1]}", temporary_file)
|
|
skip_result = False
|
|
except FileNotFoundError as e:
|
|
messages.error(request, 'Struttura del file .zip errata.')
|
|
skip_result = True
|
|
if not skip_result:
|
|
try:
|
|
new_theme = models.Theme(
|
|
**result[0]['fields']
|
|
)
|
|
new_theme.save()
|
|
|
|
messages.success(request, _('Import finished'))
|
|
except:
|
|
messages.error(request, 'Struttura del file .json errata.')
|
|
else:
|
|
messages.error(request, 'È richiesto un file .zip')
|
|
|
|
url = reverse('admin:%s_%s_changelist' % self.get_model_info(),
|
|
current_app=self.admin_site.name)
|
|
return HttpResponseRedirect(url)
|
|
else:
|
|
context.update(self.admin_site.each_context(request))
|
|
|
|
context['title'] = _("Import")
|
|
context['form'] = form
|
|
context['opts'] = self.model._meta
|
|
|
|
request.current_app = self.admin_site.name
|
|
return TemplateResponse(request, [self.import_template_name],
|
|
context)
|
|
|
|
def changelist_view(self, request, extra_context=None):
|
|
if extra_context is None:
|
|
extra_context = {}
|
|
extra_context['has_import_permission'] = self.has_import_permission(request)
|
|
return super().changelist_view(request, extra_context)
|
|
|