Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing Foreign Key objects in Django

I have been working on developing some RESTful Services in Django to be used with both Flash and Android apps.

Developing the services interface has been quite simple, but I have been running into an issue with serializing objects that have foreign key and many to many relationships.

I have a model like this:

class Artifact( models.Model ):     name                = models.CharField( max_length = 255 )     year_of_origin      = models.IntegerField( max_length = 4, blank = True, null = True )     object_type         = models.ForeignKey( ObjectType, blank = True, null = True )     individual          = models.ForeignKey( Individual, blank = True, null = True )     notes               = models.TextField( blank = True, null = True ) 

Then I would perform a query on this model like this, using select_related(), to be sure that foreign key relationships are followed:

artifact = Artifact.objects.select_related().get(pk=pk) 

Once I have the object, I serialize it, and pass that back to my view:

serializers.serialize( "json", [ artifact ] ) 

This is what I get back, note that the foreign keys (object_type and individual) are just the id's to their related objects.

[       {             pk: 1             model: "artifacts.artifact"             fields: {                 year_of_origin: 2010                 name: "Dummy Title"                 notes: ""                 object_type: 1                 individual: 1             }       } ] 

This is great, but what I was hoping for when using select_related() was that it would automatically populate the foreign key fields with the related object, not just the object's id.

I am recent convert to Django, but put in a fair amount of time developing with CakePHP.

What I really like about the Cake ORM was that it would follow the relationships and create nested objects by default, with the ability to unbind the relationships when you were calling your query.

This made it very easy to abstract the services in a way that did not require any intervention on a case by case basis.

I see that Django does not do this by default, but is there a way to automatically serialize an object and all of it's related objects? Any tips or reading would be much appreciated.

like image 877
Kieran Lynn Avatar asked Sep 20 '10 16:09

Kieran Lynn


People also ask

How do you serialize an object in Django REST framework?

Creating and Using Serializers To create a basic serializer one needs to import serializers class from rest_framework and define fields for a serializer just like creating a form or model in Django.

How do I change the ForeignKey value in Django REST framework?

As stated in the documentation, you will need to write your own create() and update() methods in your serializer to support writable nested data. You will also need to explicitly add the status field instead of using the depth argument otherwise I believe it won't be automatically added to validated_data .

What is serializing in django?

Django's serialization framework provides a mechanism for “translating” Django models into other formats. Usually these other formats will be text-based and used for sending Django data over a wire, but it's possible for a serializer to handle any format (text-based or not).


1 Answers

I had a similar requirement although not for RESTful purposes. I was able to achieve what I needed by using a "full" serializing module, in my case Django Full Serializers. This is part of wadofstuff and is distributed under the new BSD license.

Wadofstuff makes this quite easy. For e.g. in your case you'd need to do the following:

First, install wadofstuff.

Second, add the following setting to your settings.py file:

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

Third, make a slight change to the code used for serialization:

artifact = Artifact.objects.select_related().get(pk=pk) serializers.serialize( "json", [ artifact ], indent = 4,      relations = ('object_type', 'individual',)) 

The key change is the relations keyword parameter. The only (minor) gotcha is to use the name of the fields forming the relation not the names of the related models.

Caveat

From the documentation:

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.

(Emphasis added)

Hope this helps.

like image 99
Manoj Govindan Avatar answered Sep 22 '22 04:09

Manoj Govindan