Blog Posts API

The models

In this example we’re working from two related models:

models.py

from django.db import models
from django.template.defaultfilters import slugify
import uuid

def uuid_str():
    return str(uuid.uuid1())


RATING_CHOICES = ((0, 'Awful'),
                  (1, 'Poor'),
                  (2, 'OK'),
                  (3, 'Good'),
                  (4, 'Excellent'))

MAX_POSTS = 10

class BlogPost(models.Model):
    key = models.CharField(primary_key=True, max_length=64, default=uuid_str, editable=False)
    title = models.CharField(max_length=128)
    content = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    slug = models.SlugField(editable=False, default='')

    def save(self, *args, **kwargs):
        """
        For the purposes of the sandbox, limit the maximum number of stored models.
        """
        self.slug = slugify(self.title)
        super(self.__class__, self).save(*args, **kwargs)
        for obj in self.__class__.objects.order_by('-created')[MAX_POSTS:]:
            obj.delete()


class Comment(models.Model):
    blogpost = models.ForeignKey(BlogPost, editable=False, related_name='comments')
    username = models.CharField(max_length=128)
    comment = models.TextField()
    rating = models.IntegerField(blank=True, null=True, choices=RATING_CHOICES, help_text='How did you rate this post?')
    created = models.DateTimeField(auto_now_add=True)

Creating the resources

We need to create two resources that we map to our two existing models, in order to describe how the models should be serialized. Our resource descriptions will typically go into a module called something like ‘resources.py’

resources.py

from django.core.urlresolvers import reverse
from djangorestframework.resources import ModelResource
from blogpost.models import BlogPost, Comment


class BlogPostResource(ModelResource):
    """
    A Blog Post has a *title* and *content*, and can be associated with zero or more comments.
    """
    model = BlogPost
    fields = ('created', 'title', 'slug', 'content', 'url', 'comments')
    ordering = ('-created',)

    def comments(self, instance):
        return reverse('comments', kwargs={'blogpost': instance.key}) 


class CommentResource(ModelResource):
    """
    A Comment is associated with a given Blog Post and has a *username* and *comment*, and optionally a *rating*. 
    """
    model = Comment
    fields = ('username', 'comment', 'created', 'rating', 'url', 'blogpost')
    ordering = ('-created',)
    
    def blogpost(self, instance):
        return reverse('blog-post', kwargs={'key': instance.blogpost.key}) 

Creating views for our resources

Once we’ve created the resources there’s very little we need to do to create the API. For each resource we’ll create a base view, and an instance view. The generic views ListOrCreateModelView and InstanceModelView provide default operations for listing, creating and updating our models via the API, and also automatically provide input validation using default ModelForms for each model.

urls.py

from django.conf.urls.defaults import patterns, url
from djangorestframework.views import ListOrCreateModelView, InstanceModelView
from blogpost.resources import BlogPostResource, CommentResource


urlpatterns = patterns('',
    url(r'^$', ListOrCreateModelView.as_view(resource=BlogPostResource), name='blog-posts-root'),
    url(r'^(?P<key>[^/]+)/$', InstanceModelView.as_view(resource=BlogPostResource), name='blog-post'),
    url(r'^(?P<blogpost>[^/]+)/comments/$', ListOrCreateModelView.as_view(resource=CommentResource), name='comments'),
    url(r'^(?P<blogpost>[^/]+)/comments/(?P<id>[^/]+)/$', InstanceModelView.as_view(resource=CommentResource)),
)

Project Versions

Table Of Contents

Previous topic

Code Highlighting API

Next topic

Sandbox Root API

This Page