Login

JSON serializer supporting natural primary keys

Author:
bdauvergne
Posted:
March 25, 2014
Language:
Python
Version:
1.6
Score:
0 (after 0 ratings)

Copy this file into your_app/serializer.py, and add this to your settings:

SERIALIZATION_MODULES = {
    'json': 'your_app.serializer',
}

Now you can dump your models with the classical dumpdata -n command and load it with loaddata and get support for natural primary keys and not only with foreign keys and many to many fields.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import json

from django.utils import six
from django.core.serializers.json import Serializer as JSONSerializer
from django.core.serializers.python import Deserializer as \
    PythonDeserializer, _get_model
from django.core.serializers.base import DeserializationError

class Serializer(JSONSerializer):
    def get_dump_object(self, obj):
        d = super(Serializer, self).get_dump_object(obj)
        if self.use_natural_keys and hasattr(obj, 'natural_key'):
            d['pk'] = obj.natural_key()
        return d

def Deserializer(stream_or_string, **options):
    """
    Deserialize a stream or string of JSON data.
    """
    if not isinstance(stream_or_string, (bytes, six.string_types)):
        stream_or_string = stream_or_string.read()
    if isinstance(stream_or_string, bytes):
        stream_or_string = stream_or_string.decode('utf-8')
    try:
        objects = json.loads(stream_or_string)
        for obj in objects:
            Model = _get_model(obj['model'])
            if isinstance(obj['pk'], (tuple, list)):
                o = Model.objects.get_by_natural_key(*obj['pk'])
                obj['pk'] = o.pk
        for obj in PythonDeserializer(objects, **options):
            yield obj
    except GeneratorExit:
        raise
    except Exception as e:
        # Map to deserializer error
        six.reraise(DeserializationError, DeserializationError(e), sys.exc_info()[2])

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 6 months ago

Comments

depaolim (on December 3, 2014):

Thanks bdauvergne for your snippet.

I propose to slightly modify for new objects (even if they do not exist in db)

 if isinstance(obj['pk'], (tuple, list)):                              
     try:                                                              
        o = Model.objects.get_by_natural_key(*obj['pk'])        
        obj['pk'] = o.pk                                              
     except Model.DoesNotExist:                                  
        del obj['pk']

#

Please login first before commenting.