diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2020-07-25 20:26:21 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2020-07-25 20:26:21 +0200 |
commit | bb8a2d51376614f163b0aaf729f2fddc3b41d8ad (patch) | |
tree | 487321e3273f26860c591841b47a206a5e855d65 /ishtar_common/admin.py | |
parent | 329e60a808267eb89fea5008e7f4ce1a9a79ed6f (diff) | |
download | Ishtar-bb8a2d51376614f163b0aaf729f2fddc3b41d8ad.tar.bz2 Ishtar-bb8a2d51376614f163b0aaf729f2fddc3b41d8ad.zip |
Admin: Import/export as JSON for types and importers
Diffstat (limited to 'ishtar_common/admin.py')
-rw-r--r-- | ishtar_common/admin.py | 111 |
1 files changed, 106 insertions, 5 deletions
diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py index 71dc2cbdc..e606a81e7 100644 --- a/ishtar_common/admin.py +++ b/ishtar_common/admin.py @@ -67,6 +67,9 @@ from ishtar_common.apps import admin_site from ishtar_common.utils import get_cache, create_slug from ishtar_common import forms as common_forms +from ishtar_common.serializers import restore_serialized, IMPORT_MODEL_LIST +from ishtar_common.serializers_utils import generic_get_results, \ + serialization_info from archaeological_files import forms as file_forms from archaeological_files_pdl import forms as file_pdl_forms from archaeological_operations import forms as operation_forms @@ -113,7 +116,7 @@ def change_value(attribute, value, description): return _change_value -def export_as_csv_action(description=_(u"Export selected as CSV file"), +def export_as_csv_action(description=_("Export selected as CSV file"), fields=None, exclude=None, header=True): """ This function returns an export csv action @@ -206,6 +209,44 @@ def export_as_geojson_action( return export_as_geojson +def serialize_action(dir_name, model_list): + def _serialize_action(modeladmin, request, queryset): + if model_list: + modellist = model_list[:] + else: + modellist = [modeladmin.model] + opts = modeladmin.model._meta + result = generic_get_results( + modellist, dir_name, + result_queryset={opts.object_name: queryset}) + basename = str(opts).replace('.', '_') + in_memory = BytesIO() + zip = zipfile.ZipFile(in_memory, "a") + for key in result.keys(): + __, model_name = key + zip.writestr(dir_name + os.sep + model_name + ".json", result[key]) + + # info + zip.writestr("info.json", json.dumps(serialization_info(), indent=2)) + + # fix for Linux zip files read in Windows + for file in zip.filelist: + file.create_system = 0 + zip.close() + response = HttpResponse(content_type='application/zip') + response['Content-Disposition'] = 'attachment; filename={}.zip'.format( + basename + ) + in_memory.seek(0) + response.write(in_memory.read()) + return response + return _serialize_action + + +SERIALIZE_DESC = _("Export selected as Ishtar (zipped JSON)") +serialize_type_action = serialize_action("types", None) +serialize_type_action.short_description = SERIALIZE_DESC + TokenAdmin.raw_id_fields = ('user',) admin_site.register(Token, TokenAdmin) @@ -693,6 +734,61 @@ class ImportGEOJSONActionAdmin(object): {'file_form': form, 'current_action': 'import_geojson'}) +class ImportJSONForm(forms.Form): + json_file = forms.FileField( + _("Zipped JSON file"), + help_text=_("Import from a zipped JSON file generated by Ishtar") + ) + + +class ImportJSONActionAdmin(admin.ModelAdmin): + change_list_template = "admin/json_change_list.html" + import_keys = ['slug', 'txt_idx'] + + def get_urls(self): + urls = super(ImportJSONActionAdmin, self).get_urls() + my_urls = [ + url(r'^import-from-json/$', self.import_json), + ] + return my_urls + urls + + def import_json(self, request): + form = None + + if 'apply' in request.POST: + form = ImportJSONForm(request.POST, request.FILES) + if form.is_valid(): + with tempfile.TemporaryDirectory() as tmpdirname: + filename = tmpdirname + os.sep + "export.zip" + with open(filename, "wb+") as zipped_file: + for chunk in request.FILES['json_file'].chunks(): + zipped_file.write(chunk) + result = None + result = restore_serialized(filename) + try: + result = restore_serialized(filename) + except ValueError as e: + self.message_user(request, str(e), + level=messages.ERROR) + if result: + for model, count in result: + self.message_user( + request, + str(_("{} {}(s) created/updated.")).format( + count, model)) + url = reverse( + 'admin:%s_%s_changelist' % ( + self.model._meta.app_label, self.model._meta.model_name) + ) + return HttpResponseRedirect(url) + if not form: + form = ImportJSONForm() + return render( + request, 'admin/import_from_file.html', + {'file_form': form, 'current_action': 'import_json'} + ) + + class AdminRelatedTownForm(forms.ModelForm): class Meta: model = models.Town.children.through @@ -744,12 +840,12 @@ class TownAdmin(ImportGEOJSONActionAdmin, ImportActionAdmin): admin_site.register(models.Town, TownAdmin) -class GeneralTypeAdmin(ImportActionAdmin): +class GeneralTypeAdmin(ImportActionAdmin, ImportJSONActionAdmin): list_display = ['label', 'txt_idx', 'available', 'comment'] search_fields = ('label', 'txt_idx', 'comment',) list_filter = ('available',) save_on_top = True - actions = [export_as_csv_action()] + actions = [export_as_csv_action(), serialize_type_action] prepopulated_fields = {"txt_idx": ("label",)} @csrf_protect_m @@ -995,9 +1091,14 @@ if settings.USE_LIBREOFFICE: importer_type_actions.append(generate_libreoffice_template) -class ImporterTypeAdmin(admin.ModelAdmin): +serialize_importer_action = serialize_action("common_imports", + IMPORT_MODEL_LIST) +serialize_importer_action.short_description = SERIALIZE_DESC + + +class ImporterTypeAdmin(ImportJSONActionAdmin): list_display = ('name', 'associated_models', 'available') - actions = importer_type_actions + actions = importer_type_actions + [serialize_importer_action] admin_site.register(models.ImporterType, ImporterTypeAdmin) |