My favorites | Sign in
Project Logo
                
Search
for
Updated May 23, 2009 by mattimustang
Labels: Featured, Phase-Implementation
DjangoFullSerializers  
Documentation and examples for the Wad of Stuff Django Full Serializers

Introduction

The wadofstuff.django.serializers python module extends Django's built-in serializers, adding 3 new capabilities inspired by the Ruby on Rails JSON serializer. These parameters allow the developer more control over how their models are serialized. The additional capabilities are:

  • excludes - a list of fields to be excluded from serialization. The excludes list takes precedence over the fields argument.
  • extras - a list of non-model field properties or callables to be serialized.
  • relations - a list or dictionary of model related fields to be followed and serialized.

Serialization Formats

The module currently support serializing to JSON and Python only.

Source

The latest stable release for the serialization module can be obtained by:

The latest development source can be obtained here:

Examples

Project Settings

You must add the following to your project's settings.py to be able to use the JSON serializer.

SERIALIZATION_MODULES = {
    'json': 'wadofstuff.django.serializers.json'
}

Backwards Compatibility

The Wad of Stuff serializers are 100% compatible with the Django serializers when serializing a model. When deserializing a data stream the the Deserializer class currently only works with serialized data returned by the standard Django serializers.

>>> from django.contrib.auth.models import Group
>>> from django.core import serializers
>>> print serializers.serialize('json', Group.objects.all(), indent=4)
[
    {
        "pk": 2,
        "model": "auth.group",
        "fields": {
            "name": "session",
            "permissions": [
                19
            ]
        }
    }
]

Excludes

>>> print serializers.serialize('json', Group.objects.all(), indent=4, excludes=('permissions',))
[
    {
        "pk": 2,
        "model": "auth.group",
        "fields": {
            "name": "session"
        }
    }
]

Extras

The extras option allows the developer to serialize properties of a model that are not fields. These properties may be almost any standard python attribute or method. The only limitation being that you may only serialize methods that do not require any arguments.

For demonstration purposes in this example I monkey patch the Group model to have a get_absolute_url() method.

>>> def get_absolute_url(self):
...     return u'/group/%s' % self.name
...
>>> Group.get_absolute_url = get_absolute_url
>>> print serializers.serialize('json', Group.objects.all(), indent=4, extras=('__unicode__','get_absolute_url'))
[
    {
        "pk": 2,
        "model": "auth.group",
        "extras": {
            "get_absolute_url": "/group/session",
            "__unicode__": "session"
        },
        "fields": {
            "name": "session",
            "permissions": [
                19
            ]
        }
    }
]

Relations

The Wad of Stuff serializers allow you to follow related fields of a model to any depth you wish and serialize those as well. This is why it is considered a "full serializer" as opposed to Django's built-in serializers that only return the related fields primary key value.

When using the relations argument to the serializer you may specify either a list of fields to be serialized or a dictionary of key/value pairs. The dictionary keys are the field names of the related fields to be serialized and the values are the arguments to pass to the serializer when processing that field.

>>> print serializers.serialize('json', Group.objects.all(), indent=4, relations=('permissions',))
[
    {
        "pk": 2,
        "model": "auth.group",
        "fields": {
            "name": "session",
            "permissions": [
                {
                    "pk": 19,
                    "model": "auth.permission",
                    "fields": {
                        "codename": "add_session",
                        "name": "Can add session",
                        "content_type": 7
                    }
                }
            ]
        }
    }
]

Only serializing a particular field of a relation

>>> print serializers.serialize('json', Group.objects.all(), indent=4, relations={'permissions':{'fields':('codename',)}})
[
    {
        "pk": 2,
        "model": "auth.group",
        "fields": {
            "name": "session",
            "permissions": [
                {
                    "pk": 19,
                    "model": "auth.permission",
                    "fields": {
                        "codename": "add_session"
                    }
                }
            ]
        }
    }
]

Serializing a relation of a relation

>>> print serializers.serialize('json', Group.objects.all(), indent=4, relations={'permissions':{'relations':('content_type',)}})
[
    {
        "pk": 2,
        "model": "auth.group",
        "fields": {
            "name": "session",
            "permissions": [
                {
                    "pk": 19,
                    "model": "auth.permission",
                    "fields": {
                        "codename": "add_session",
                        "name": "Can add session",
                        "content_type": {
                            "pk": 7,
                            "model": "contenttypes.contenttype",
                            "fields": {
                                "model": "session",
                                "name": "session",
                                "app_label": "sessions"
                            }
                        }
                    }
                }
            ]
        }
    }
]

Excluding a field from a relation of a relation

>>> print serializers.serialize('json', Group.objects.all(), indent=4, relations={'permissions':{'relations':{'content_type':{'excludes':('app_label',)}}}})
[
    {
        "pk": 2,
        "model": "auth.group",
        "fields": {
            "name": "session",
            "permissions": [
                {
                    "pk": 19,
                    "model": "auth.permission",
                    "fields": {
                        "codename": "add_session",
                        "name": "Can add session",
                        "content_type": {
                            "pk": 7,
                            "model": "contenttypes.contenttype",
                            "fields": {
                                "model": "session",
                                "name": "session"
                            }
                        }
                    }
                }
            ]
        }
    }
]

Comment by jumican, Feb 26, 2009

Extremely helpful - thank you.

Comment by goo...@i-sh.me.uk, Mar 11, 2009

Brilliant serializer, proven very useful. Thanks a lot

Comment by tony.mcdonald, Apr 05, 2009

The 'extras' facility has just saved me heaps of time - I had no idea why it wasn't being serialized, and fortunately found your post.

many thanks! tone

Comment by tony.mcdonald, Apr 11, 2009

I've passed on this link to the guys doing great work at the Washington Times <http://opensource.washingtontimes.com/> as they (Justin) have been working on a terrific django app called django-apibuilder which is a beautiful fit for this serializer.

Comment by justquick, Apr 18, 2009

yes, the wad is right now being used in the development branch of the django-apibuilder

Comment by Flashing...@gmail.com, Apr 30, 2009

Short question about the possibilities to serialize fields inherited by subclassing a django model. There's basically something like this:

from django.db import models

class BaseModel(models.Model):
    name = models.CharField()
    
class InheritModel(BaseModel):
    content = models.TextField()
    
class OtherModel(BaseModel):
    date = models.DateTimeField()
     

serializing either InheritModel? or OtherModel? does not yield serialization of the name field of BaseModel?, and I couldn't find how to make the link to the related field on a quick glance. Tried both of these options

serialize('json',InheritModel.objects.all(), relations = {'basemodel':{'fields':('name',)}}) 
serialize('json',InheritModel.objects.all(), relations = {'basemodel_ptr':{'fields':('name',)}}) # which is the fields name specified via InheritModel._meta

Any suggestions on how to solve, or would it need to add some more code to the Serializer class?

Cheers

Comment by Flashing...@gmail.com, Apr 30, 2009

PS: BaseModel? is not an abstract = True class.

Comment by Flashing...@gmail.com, Apr 30, 2009

Well, looked a bit more into it and figured out, that django.db.models.fields.OneToOneField , which handles inheritance, is set to serialize = False on inheritance which skipped the serialization. I've added another loop which iterates over <obj>._meta.parents and updates self._fields with the values from the parent's object fields. You'll find the the svn diff in the issues. Hope I was able to enhance this awesome serializer. :)

Cheers,

Comment by sergio.berlotto, Jul 31, 2009

How to i serialize infinite model Tree, like this:

class Item(models.Model):

item_name: models.CharField?(max_length=30) parent_item: models.ForeignKey?(self)

thank you

Comment by mattimustang, Aug 01, 2009

You have to explicitly specify to depth you want to serialize to. e.g this will serial 3 relations deep.

>>> print serializers.serialize('json', Group.objects.all(), indent=4,
    relations={
        'parent_item':{
            'relations':{
                'parent_item':{
                    'relations':('parent_item',)
                }
            }
        }
    })
Comment by delwyn.d, Aug 03, 2009

Brilliant serializer, using it in a few django apps. What is the best way to use it with the google app engine?

Thanks in advance.

Comment by mattimustang, Aug 03, 2009

Hi,

Sorry I haven't tried it with GAE. If you can get it working let me know and pass along any patches.

Comment by xaralis93, Nov 05, 2009

I am having little trouble when trying to serialize a model created by multi-table model inheritance.

I have tracked down the source to the fact that django marks the link from model to it's parent (OneToOneField?) with serialize=False. This results in not serializing the field by the serializer.

I need to serialize the fields from the parent as well.

Do you have some hint how to prevent Django from marking it up like this?

Comment by fuzzyman, Nov 13, 2009

In the extras documentation you say: These properties may be almost any standard python attribute or method.

But it seems to me (from experimentation) that they can't be any attribute, they have to be a method that takes no arguments.

In addition if this method returns anything other than a string then the object is serialized as a string. I need to serialize a list of dictionaries and this is coming out as a string in the json.

This makes me a sad bunny as I then have to serialize it myself. :-(

Comment by johnvmccollum, Nov 17, 2009

Great work on the serializer, thank you very, very much!


Sign in to add a comment
Hosted by Google Code