django+angular
— 7 min read

End to end web app with Django-Rest-Framework & AngularJS.

[Part 1].

A REST API allows your users to interact with your website from anything that can send an HTTP request. In this post we will create a RESTful api in Django using the Django-Rest-Framework. And we will access this api using a client developed under AngularJS.

To utilize the API developed in Django, we are going to use $http & $q services in Angular. The $http service is a core Angular service that facilitates communication with the remote HTTP servers via browser’s XMLHttpRequest object or via JSONP. $q is promise implementation that comes with Angular.

Preparing the environment

First thing to do is to prepare the environment, I suppose that most of you use virtualenv.

1 >  virtualenv django-angular
2 >  cd django-angular
3 >  source bin/activate

Clone this repos :

https://github.com/mouradmourafiq/django-angular-blog

Checkout to part1 branch.

1 >  git clone https://github.com/mouradmourafiq/django-angular-blog
2 >  cd django-angular-blog
3 >  git checkout part1

Install the packages.

1 >  pip install -r blog/requirements.pip

Copy the local_settings.py from templates/template_local_settings.py

1 >  cp blog/templates/template_local_settings.py blog/blog/local_settings.py

and update the file with the correct informations.

The backend

We will create a simple model for our posts app.

 1 from django.db import models
 2 from django.template.defaultfilters import slugify
 3 
 4 
 5 class Post(models.Model):
 6     """
 7     An item created by a user.
 8     """
 9     title = models.CharField(max_length=100)
10     slug = models.SlugField()
11     description = models.TextField(blank=True, help_text=(
12         "If omitted, the description will be the post's title."))
13     is_active = models.BooleanField(default=True, blank=True)
14     created_on = models.DateTimeField(auto_now_add=True)
15     updated_on = models.DateTimeField(auto_now=True)
16 
17     def save(self, *args, **kwargs):
18         self.do_unique_slug()
19         if not self.description:
20             self.description = self.title
21         super(Post, self).save(*args, **kwargs)
22 
23     def do_unique_slug(self):
24         """
25         Ensures that the slug is always unique for this post
26         """
27         if not self.id:
28             # make sure we have a slug first
29             if not len(self.slug.strip()):
30                 self.slug = slugify(self.title)
31 
32             self.slug = self.get_unique_slug(self.slug)
33             return True
34 
35         return False
36 
37     def get_unique_slug(self, slug):
38         """
39         Iterates until a unique slug is found
40         """
41         orig_slug = slug
42         counter = 1
43 
44         while True:
45             posts = Post.objects.filter(slug=slug)
46             if not posts.exists():
47                 return slug
48 
49             slug = '%s-%s' % (orig_slug, counter)
50             counter += 1

Now we have our model we can create a serializer in order to provide a way of serializing and deserializing the post instances into representations such as json.

DRF comes with a HyperlinkedModelSerializer class, which is a serializer classe that map closely to model definitions. rather than primary keys, it uses hyperlinks to represent relationships.

 1 from rest_framework import serializers
 2 from posts.models import Post
 3 
 4 
 5 class PostSerializer(serializers.HyperlinkedModelSerializer):
 6     api_url = serializers.SerializerMethodField('get_api_url')
 7 
 8     class Meta:
 9         model = Post
10         fields = ('id', 'title', 'description', 'created_on', 'url', 'api_url')
11         read_only_fields = ('id', 'created_on')
12 
13     def get_api_url(self, obj):
14         return "#/post/%s" % obj.id

Finally, we need to write our views and urls. We will use the class based views, rather than function based views.

 1 from rest_framework import generics
 2 from posts.models import Post
 3 from posts.serializers import PostSerializer
 4 
 5 
 6 class PostList(generics.ListCreateAPIView):
 7     """
 8     List all boards, or create a new board.
 9     """
10     model = Post
11     serializer_class = PostSerializer
12 
13 
14 class PostDetail(generics.RetrieveUpdateDestroyAPIView):
15     """
16     Retrieve, update or delete a board instance.
17     """
18     model = Post
19     serializer_class = PostSerializer
 1 from django.conf.urls import patterns, include, url
 2 from rest_framework.urlpatterns import format_suffix_patterns
 3 from posts import views
 4 
 5 urlpatterns = patterns('',
 6     url(r'^$', views.PostList.as_view(), name='post-list'),
 7     url(r'^(?P<pk>[0-9]+)/$', views.PostDetail.as_view(), name='post-detail'),
 8 )
 9 
10 
11 urlpatterns = format_suffix_patterns(urlpatterns)

Django REST Framework supports generating human-friendly HTML output for each resource when the HTML format is requested. These pages allow for easy browsing of resources, as well as forms for submitting data to the resources using POST, PUT, and DELETE.

You can test for yourself : http://localhost:8000/posts/

The next part of this tutorial will deal with the front end of this app with angularJs.