Fernando Correia’s Weblog

August 2, 2008

Returning DTOs from PyAMF

Filed under: Software Development — Fernando Correia @ 12:14 pm
Tags: , ,

Serializing Google App Engine model objects using the AMF protocol is very efficient. AMF even supports references to objects, so repeated serialization of references to the same object won’t waste bandwidth.

For instance, if we have a model like this:

class Project(db.Model):
    code = db.IntegerProperty()
    name = db.StringProperty()
    department = db.IntegerProperty(default=0)
    created_at = db.DateTimeProperty(auto_now_add=True)
    modified_at = db.DateTimeProperty(auto_now=True)

class ProjectParticipant(db.Model):
    project = db.ReferenceProperty(Project, collection_name='participants')
    name = db.StringProperty()
    created_at = db.DateTimeProperty(auto_now_add=True)
    modified_at = db.DateTimeProperty(auto_now=True)

And we return a list of 5 participants of 2 projects, each project’s data could be serialized only once, although on the client side we will have the project data in each participant instance. This is good and PyAMF supports this feature. [Edited after some clarification from Nick Joyce.]

But sometimes we may want more control over what is serialized. For instance, we can have an object that has references to 5 other objects. But our client may not need to use their data, so it would be a waste to serialize it.

We can have fine control over what is serialized, with more work on the server side, by creating a data transfer object (DTO) that will be returned. That way we can decide whether we want deep or shallow serialization. We can also restrict the data that will be serialized and return keys or references as we think will be better for use on client side.

This is an example of the DTO approach:

class DTO(object):
    pass

class ProjectParticipantsService:
    def get(self, key):
        return self.to_dto(ProjectParticipant.get(key))

    def to_dto(self, participant):
        dto = DTO()
        dto._key = str(participant.key())
        dto._id = participant.key().id()
        dto.project_key = str(participant.project.key())
        dto.name = participant.name
        dto.created_at = participant.created_at
        dto.modified_at = participant.modified_at
        return dto

A generic DTO class is used. I don’t see much point on creating a specific class, like you would do on Java. This way, you only have one place where you control your DTO’s structure. DRY.

Some caveats that may bite you when you are coding late at night:

  • Your DTO cannot be a direct instance of object, like dto = object(). Instances of object cannot be extended with dynamic attributes.
  • Be sure to convert the key to a string. If you try to serialize the key itself, like dto.project_key = participant.project.key(), there will be an error like “AttributeError: ‘str’ object has no attribute ‘iteritems'”.

I published an example at github.

“At last! It works.” (Cosmix)

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: