Consuming RESTful API with RESTframework

As explained in previous post, we’re going to demonstrate how RESTframework handles REST web services. I’ll be consuming a simple Django demo web service created in previous post, so either grab the sources or read the post and build it yourself. Assuming you have this service running on localhost, port 8000, we can continue.

First, download RESTframework from GitHub. With git client, simply type in terminal:

$ git clone git@github.com:ivasic/RESTframework.git

The quickest way to get RESTframework into your project is just including all the files from RFClasses  folder. RF does not have any external dependencies so building shouldn’t be a problem.

RFClasses

RFClasses

Now, we’ll also need JSONKit to parse API response and MBProgressHUD to show some progress. Grab both from GitHub and add to your project.

Fetching objects list

We’ll have 2 view controllers in our demo app. One will be a simple object list and the other one will be, even more simple, view controller for creating a new object. First, we’re going to show how to fetch the object list. We’ll need a GET request to /objects/ URL and we’ll need to parse the JSON array we get in response and show in the table view.

RFRequest* r = [RFRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8000/"] type:RFRequestMethodGet resourcePathComponents:@"objects", nil];
[MBProgressHUD showHUDAddedTo:self.view animated:YES].labelText = NSLocalizedString(@"Loading...", @"");
[RFService execRequest:r completion:^(RFResponse* response) {
	[MBProgressHUD hideHUDForView:self.view animated:YES];
 
	if (response.error) {
		UIAlertView* aiv = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", @"") message:response.error.localizedDescription delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
		[aiv show];
		return;
	}
 
	self.dataSource = [response.dataValue objectFromJSONData];
	[self.tableView reloadData];
}];

So, what we’re doing in this code snippet is:

  • Creating a GET RFRequest with appropriate URL and resource path
  • Attaching MBProgressHUD to our view to show spinner progress
  • Executing RFRequest and defining the block to execute after RFResponse is received
  • Inside this block, we simply check for errors, parse the response, add to our tableView dataSource and reloading the table
You can see all this in action in the project sample attached to this blog post (at the bottom).

Creating new objects

Our view controller for creating new objects is responsible for creating POST requests to /objects/ URL. Again, very simple, you just need to do this:

RFRequest* r = [RFRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8000/"] type:RFRequestMethodPost resourcePathComponents:@"objects", @"", nil];
 
[r addParam:self.txtName.text forKey:@"name"];
[r addParam:self.lblDate.text forKey:@"date"];
 
[MBProgressHUD showHUDAddedTo:self.view animated:YES].labelText = NSLocalizedString(@"Submitting...", @"");
[RFService execRequest:r completion:^(RFResponse* response) {
	[MBProgressHUD hideHUDForView:self.view animated:YES];
 
	if (response.error) {
		UIAlertView* aiv = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", @"") message:response.error.localizedDescription delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
		[aiv show];
		return;
	}
 
	UIAlertView* aiv = [[[UIAlertView alloc] initWithTitle:@"Success" message:@"Success" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
	[aiv show];
 
	[self.navigationController popViewControllerAnimated:YES];
}];

Similar to our previous snippet, but this time we also add some parameters to the request – name and date strings.

This is a brief overview with sample Xcode project of how RESTframework consumes RESTful web APIs. Questions welcomed via comments as usual.

 

Download project: RESTframework demo Xcode project download

Building RESTful API with Django

In order to demonstrate how RESTframework for Cocoa works, I’m going to create a small RESTful API demo in Django/Python and use that as a demo web service we’re gonna query from our soon-to-be demo iOS app. Hopefully, you can also pick up a thing or two from this tutorial as well since Django seems to be a very powerful framework for building RESTful APIs with. If you don’t want to bother with Django, you can simply download the project (see the end of this post) and run it as a demo web service. Next post will explain how to use my RESTframework to consume this web service.

Requirements

You’ll need Python, of course, and I’ve tested this on v2.7 although I’m pretty sure it should also work on v2.6 and possibly v2.5. Then you’ll need django and djangorestframework both available for install with pip or easy_install.

Django project

Create a new django project and the first django app.

$ django-admin.py startproject DjangoTest
$ cd DjangoTest
$ django-admin.py startapp api

Now we need to modify our initial project settings. For the sake of simplicity, I’ll be using SQLite3 database since it doesn’t require any installation or setup. To do this, edit settings.py in your project dir.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'database.db',                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

Another thing we need to do in settings.py is to add your app and djangorestframework to the installed apps section.

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
    'DjangoTest.api',
    'djangorestframework',
)

Okay, now let’s run and test if it worked.

$ python manage.py runserver

Now go to http://localhost:8000/ and make sure you see “It worked” message.

Next step is creating some resources for our RESTful API. I’ve created a simple model to hold a name and creation date. Looks like this:

class Object(models.Model):
	name = models.CharField(max_length=50)
	date = models.DateTimeField()

We’re almost there. We need to sync our database now after we’ve created the model (do this every time you change the model, see more info here)

$ python manage.py syncdb

RESTful API using django-rest-framework

Now our django project is ready. Using djangorestframework we will add RESTful API interface for our ‘api’ app. Assuming you’ve installed it correctly, all we need to do is to create another python file where we will store our resources. Name it resources.py and put this inside:

from djangorestframework.resources import ModelResource
from api.models import Object
 
class ObjectResource(ModelResource):
	model = Object
	fields = ('name', 'date')

When this is done, we need to add some URLs where our resources will be located. I’m using nifty views provided by djangorestframework which work with your models without a single line of code. You get 2 URLs for viewing a list of objects (or creating a new one) and one for viewing your object details. urls.py looks like this:

from django.conf.urls.defaults import patterns, include, url
 
# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()
from djangorestframework.views import ListOrCreateModelView, InstanceModelView
from api.resources import ObjectResource
 
urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'DjangoTest.views.home', name='home'),
    # url(r'^DjangoTest/', include('DjangoTest.foo.urls')),
 
    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
 
    # Uncomment the next line to enable the admin:
    # url(r'^admin/', include(admin.site.urls)),
 
    url(r'^objects/$', ListOrCreateModelView.as_view(resource=ObjectResource), name='object-root'),
    url(r'^objects/(?P[^/]+)/$', InstanceModelView.as_view(resource=ObjectResource), name='object'),
)

That’s it. Save and run your project and you’ll be able to access your resources at http://localhost:8000/objects/
For example, querying an URL like this one (providing you added an object with id=1) http://localhost:8000/objects/1/?_accept=application/json would result in this:

{"date": "2011-11-28 09:38:21", "name": "Test"}

Download sample project

Help yourself with the sources for this project ready to unzip & run. You can download the project here – DjangoRESTfulAPI.