Django app that automates objects tree serialization recursively, without any declarations.
Define new classes for every Object serialization could sound a bit boring, I coded this app to do the things automagically. Django-auto-serializer will do for you:
- Json serialization (export);
- recursively serialize all FK childrens;
- can ignore some children if you tell him how they are named (see examples above);
- M2M auto serialization;
- ignore or not autofields import/export (auto_now_add...);
- regenerates unique if needed, the same for slugfields (change_uniques = True,);
- Import a serialized Object tree, it will build up everything as before;
pip install git+https://github.com/peppelinux/django-auto-serializer.git
from my_app.models import MyModel
# get an object
myObj = MyModel.objects.first()
# object serialization
# A single object duplication
si = SerializableInstance(myObj)
#si.serialize_obj()
si.serialize_tree()
si.remove_duplicates()
# pprint(si.dict)
# Serialized entire tree, main object with childrens
si = SerializableInstance(myObj,
excluded_fields=['field1', 'field2'],
excluded_childrens = ['relatedObjClass1', 'relatedObjClass2'],
auto_fields = False,
change_uniques = True,
duplicate = True)
si.serialize_tree()
si.remove_duplicates()
import pprint
# all the fields
myObj._meta._forward_fields_map
# childrens here
myObj._meta.fields_map
myObj._meta.related_objects
# another way with NestedObjects
from django.contrib.admin.utils import NestedObjects
from django.db import DEFAULT_DB_ALIAS
# get json with pk and autofilled fields as they are
from django.core import serializers
serializers.serialize('json', [myObj], ensure_ascii=False)
# serializers.serialize() relies on
model_to_dict(myObj)
pprint(sit.dict)
for i in sit.dict['childrens']:
if i['model_name'] == 'ClassName':
pprint(i)
tree_to_str = json.dumps(si.dict, indent=2)
jsonstr_to_dict = json.loads(tree_to_str)
pprint(jsonstr_to_dict )
isi = ImportableSerializedInstance(si.dict)
isi.save()
print(isi.json())
@user_passes_test(lambda u:u.is_staff)
def import_file(request):
file_to_import = request.FILES.get('file_to_import')
# content here
url = reverse('admin:my_django_admin_url')
if not file_to_import:
return HttpResponseRedirect(url)
if not file_to_import:
# error message here
pass
jcont = json.loads(request.FILES['file_to_import'].read().decode(settings.DEFAULT_CHARSET))
isi = ImportableSerializedInstance(jcont)
isi.save()
return HttpResponseRedirect(url)
import io
import json
from django.apps import apps
from django.contrib import messages
from django.contrib.admin.models import LogEntry, ADDITION, CHANGE
from django.contrib.contenttypes.models import ContentType
from django.http.response import HttpResponse
from django_auto_serializer.auto_serializer import (SerializableInstance,
ImportableSerializedInstance)
from .models import *
def my_clone_func(modeladmin, request, queryset):
for myObj in queryset:
try:
si = SerializableInstance(myObj)
si.serialize_tree()
si.remove_duplicates()
except Exception as e:
msg = '{} cloning failed: {}'
messages.add_message(request, messages.WARNING,
msg.format(myObj, e))
try:
isi = ImportableSerializedInstance(si.dict)
isi.save()
except Exception as e:
msg = '{} cloning failed: {}'
messages.add_message(request, messages.WARNING,
msg.format(myObj, e))
msg = '{} successfully cloned.'
messages.add_message(request, messages.INFO,
msg.format(myObj))
my_clone_func.short_description = "Clone object and its configuration"
def download_obj_template(modeladmin, request, queryset):
iofile = io.StringIO()
obj_labels = []
for myObj in queryset:
try:
si = SerializableInstance(myObj)
st = si.serialize_tree()
iofile.write(json.dumps(si.dict, indent=2))
except Exception as e:
msg = '{} cloning failed: {}'
messages.add_message(request, messages.WARNING,
msg.format(myObj, e))
obj_labels.append(myObj.__str__())
file_name = 'my_export{}.json'.format('_'.join(obj_labels))
iofile.seek(0)
response = HttpResponse(iofile.read())
response['content_type'] = 'application/force-download'
response['Content-Disposition'] = 'attachment; filename={}'.format(file_name)
response['X-Sendfile'] = file_name
return response
download_obj_template.short_description = "Download object json template"
{'source_pk': 266,
'duplicate': True,
'app_name': 'cmsmenus',
'model_name': 'NavigationBar',
'object': {'created_by': 2,
'created_by_id': 2,
'is_active': True,
'name': 'test'},
'm2m': [],
'childrens': [{'source_pk': 1603,
'duplicate': True,
'app_name': 'cmsmenus',
'model_name': 'NavigationBarItem',
'object': {'created_by': 2,
'created_by_id': 2,
'order': 1,
'is_active': True,
'name': 'child 1',
'parent': 1602,
'parent_id': 1602,
'url': 'None'},
'm2m': [],
'childrens': [{'source_pk': 1604,
'duplicate': True,
'app_name': 'cmsmenus',
'model_name': 'NavigationBarItem',
'object': {'created_by': 2,
'created_by_id': 2,
'order': 2,
'is_active': True,
'menu': 266,
'menu_id': 266,
'name': 'child 2',
'url': 'None'},
'm2m': [],
'childrens': [],
'depth': 2,
'save': False,
'related_field': 'parent'}],
'depth': 1,
'save': False,
'related_field': 'menu'},
{'source_pk': 1604,
'duplicate': True,
'app_name': 'cmsmenus',
'model_name': 'NavigationBarItem',
'object': {'created_by': 2,
'created_by_id': 2,
'order': 2,
'is_active': True,
'name': 'child 2',
'parent': 1603,
'parent_id': 1603,
'url': 'None'},
'm2m': [],
'childrens': [],
'depth': 1,
'save': False,
'related_field': 'menu'},
{'source_pk': 1602,
'duplicate': True,
'app_name': 'cmsmenus',
'model_name': 'NavigationBarItem',
'object': {'created_by': 2,
'created_by_id': 2,
'modified_by': 2,
'modified_by_id': 2,
'order': 10,
'is_active': True,
'name': 'parent',
'url': 'None'},
'm2m': [],
'childrens': [{'source_pk': 1603,
'duplicate': True,
'app_name': 'cmsmenus',
'model_name': 'NavigationBarItem',
'object': {'created_by': 2,
'created_by_id': 2,
'order': 1,
'is_active': True,
'menu': 266,
'menu_id': 266,
'name': 'child 1',
'url': 'None'},
'm2m': [],
'childrens': [{'source_pk': 1604,
'duplicate': True,
'app_name': 'cmsmenus',
'model_name': 'NavigationBarItem',
'object': {'created_by': 2,
'created_by_id': 2,
'order': 2,
'is_active': True,
'menu': 266,
'menu_id': 266,
'name': 'child 2',
'url': 'None'},
'm2m': [],
'childrens': [],
'depth': 3,
'save': True,
'related_field': 'parent'}],
'depth': 2,
'save': True,
'related_field': 'parent'},
{'source_pk': 35,
'duplicate': True,
'app_name': 'cmsmenus',
'model_name': 'NavigationBarItemLocalization',
'object': {'created_by': 2,
'created_by_id': 2,
'modified_by': 2,
'modified_by_id': 2,
'is_active': True,
'language': 'en',
'name': 'adasdasd'},
'm2m': [],
'childrens': [],
'depth': 2,
'save': True,
'related_field': 'item'}],
'depth': 1,
'save': True,
'related_field': 'menu'}],
'depth': 0,
'save': True}