Skip to main content

Django auto-serializer

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;

Setup

pip install git+https://github.com/peppelinux/django-auto-serializer.git

Usage Example

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()

Some coding hints

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 )

Import dump

isi = ImportableSerializedInstance(si.dict)
isi.save()
print(isi.json())

A simple view to import a json dump

@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)

Django admin action to duplicate or export an entire tree

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"

Result (from a real NavigationBar object with items and items childs)

{'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}

Metadata

Release files for django-auto-serializer 0.4.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-auto-serializer 0.4.2
File Size Uploaded
django-auto-serializer-0.4.2.tar.gz 12.9 kB Details

Release files / django-auto-serializer-0.4.2.tar.gz

Download URL django-auto-serializer-0.4.2.tar.gz
Size 12.9 kB
Tags Source
SHA-256 checksum
How to use checksums
4bf2a8f89c6bb42a9331af33f6140e4eed836116c94e28fd511566a126c6670a
BLAKE2b-256 checksum
How to use checksums
a06fd011b5be5b735602a697183d68e5f66e0b9bd17f24bc7191962352e163ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.49.0 CPython/3.8.5

Release history Release notifications | RSS feed

This release

0.4.2 This release

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page