We've been using Django for the past couple years to build applications that communicate with mobile clients (that's kind of our thing).
This has always been our preferred backend because we are very concerned about the ability for our applications to scale and communicate across platforms. To make a long story short, being founded by two mobile developers, we've been on a quest since day one to discover the easiest and most effective way to make backend servers and apps play nicely together.
We went through a rather painful process of creating our own RESTful APIs with Django's view structure and while we were able to come up with some nifty results there was still a lot of repetitive glue code that we had to add. At PyCon 2012 we then discovered TastyPie and started using it's out of the box model creation for many of our API needs.
So as an example, we start with some Django models...
class State(BloodModel):
name = models.CharField(max_length=30)
abbrev = models.CharField(max_length=5)
country = models.ForeignKey(Country)
class Meta:
unique_together = ('abbrev', 'country')
def __str__(self):
return self.name
class BloodCenter(BloodModel):
name = models.CharField(max_length=255)
pic = models.ImageField(upload_to='center_pics', blank = True, null=True)
website = models.CharField(max_length=150, null=True, blank=True, help_text="Please use the following format: www.yourwebsite.com.")
phone = models.CharField(max_length=20)
address1 = models.CharField(max_length=100, verbose_name="Address 1")
address2 = models.CharField(max_length=100, verbose_name="Address 2", blank=True)
city = models.CharField(max_length=20)
state = models.ForeignKey(State)
zipcode = models.CharField(max_length=5)
user = models.ForeignKey(User)
latitude = models.FloatField()
longitude = models.FloatField()
class Meta:
verbose_name = "Blood Center"
def __str__(self):
return self.name
class BloodType(BloodModel):
name = models.CharField(max_length=5)
description = models.TextField(null = True, blank=True)
class Meta:
verbose_name = "Blood Type"
def __str__(self):
return self.name
class BloodLevel(BloodModel):
name = models.CharField(max_length=255)
description = models.TextField(null = True, blank=True)
image = models.ImageField(upload_to='blood_level', blank = True, null=True)
class Meta:
verbose_name = "Blood Level"
def __str__(self):
return self.name
class BloodEntry(BloodModel):
blood_center = models.ForeignKey('BloodCenter')
blood_type = models.ForeignKey('BloodType')
blood_level = models.ForeignKey('BloodLevel')
class Meta:
verbose_name = "Blood Entry"
verbose_name_plural = "Blood Entries"
def __str__(self):
return self.blood_center.name
TastyPie takes your models, serializes them and allows you to send them out. It also provides a framework for authentication which standardizes a huge piece of the puzzle. This was a big sticking point in our development prior to this because we would be producing for many platforms and coordinating authentication among developers was a big hassle. Adding TastyPie solved a huge part of our problem because we were able to create the API side of things rather easily but we still had the problem on the parsing end since we were now getting rather robust Django model data.
This is a sample of the type of data we're dealing with now...
{
address1: "270 Masonic Avenue ",
address2: "",
city: "San Francisco",
created: "2012-06-13T12:54:45",
entries: [ ],
id: 14,
latitude: 37.77902,
longitude: -122.44712,
name: "Blood Systems Research Institute",
phone: " (415) 923-5771",
pic: null,
resource_uri: "/api/v1/blood_center/14/",
state: {
abbrev: "CA",
country: {
abbrev: "US",
created: "2012-05-01T00:00:00",
id: 1,
name: "United States",
resource_uri: ""
},
created: "2012-05-01T00:00:00",
id: 6,
name: "California",
resource_uri: ""
},
website: "www.bsrisf.com",
zipcode: "94118"
}
Makes complete sense but as you can see its a bit heavy if you need to write parsers to deal with this.
Pretty soon after starting with TastyPie, RestKit came onto our radar. As an iOS developer I saw RestKit as a great compliment to dealing with TastyPie data. In RestKit you set up amappingby telling it the objects being parsed, their relationships and attributes (we are now working wonders with this and RestKit's CoreData functionality). Having set up these relationships, when you use RestKit to call your API it will automagically parse and populate the applications memory with objects that look pretty darn close to your Django models.
And here's the mapping...
RKObjectMapping* centerMapping = [RKObjectMapping mappingForClass:[BloodCenter class]];
[centerMapping mapAttributes:@"address1", @"address2", @"city", @"name", @"phone", @"pic", @"website", @"latitude", @"longitude", @"zipcode", nil];
RKObjectMapping* entryMapping = [RKObjectMapping mappingForClass:[BloodEntry class]];
[entryMapping mapAttributes:@"date", nil];
RKObjectMapping* stateMapping = [RKObjectMapping mappingForClass:[BloodState class]];
[stateMapping mapAttributes:@"abbrev", nil];
RKObjectMapping* levelMapping = [RKObjectMapping mappingForClass:[BloodLevel class]];
[levelMapping mapAttributes:@"description", @"image", @"name", nil];
RKObjectMapping* typeMapping = [RKObjectMapping mappingForClass:[BloodType class]];
[typeMapping mapAttributes:@"description", @"name", nil];
[entryMapping mapKeyPath:@"blood_level" toRelationship:@"blood_level" withMapping:levelMapping];
[entryMapping mapKeyPath:@"blood_type" toRelationship:@"blood_type" withMapping:typeMapping];
[centerMapping mapKeyPath:@"entries" toRelationship:@"entries" withMapping:entryMapping];
[centerMapping mapKeyPath:@"state" toRelationship:@"state" withMapping:stateMapping];
[[RKObjectManager sharedManager].mappingProvider setMapping:centerMapping forKeyPath:@"objects"];
Currently if you search TastyPie RestKit the only thing that comes up is a StackOverflow post about someone giving up on this stack. The TastyPie and RestKit stack most definitely works and we have a number of examples (four, in final stages of production) working beautifully. We'd love to field any developer questions (support@yetihq.com), we see this as a powerful stack we're excited to continue developing with in the future.