Django and ShimmerCat work great together too

Django + ShimmerCat

This guide shows how to setup the two parts of a very basic Django application, front-end and back-end, so that they can communicate through ShimmerCat.

The advantage of using ShimmerCat at development, vs using the bare-bones server is that you get to load your site using https:// and HTTP/2 from minute five. Also you can share your web project setup more easily with fellow team developers.

In this guide, we are actually extending the blog article ANGULARJS, REQUIREJS AND HTTP/2 PUSH that we wrote some time ago, now to use Django + Django Rest Framework at the back-end. Django Rest Framework is used to handle REST requests.

The complete project described here can be found at Github.

Starting out

As usual, we recommend that you create a folder for your project

$ mkdir django_example_project
$ cd django_example_project

The back-end code

Create a Django project and set it up

We heartily recommend using a python virtual environment to keep all the project dependencies isolated. It is also easy, if we call our virtual environment venv we just need to do:

$ virtualenv venv

Activating the environment:

$ source venv/bin/activate

To install Django and Django Rest Framework:

$ pip install Django djangorestframework

We will also require django-cors-headers:

$ pip install django-cors-headers

Let's create the Django project and call it django_api:

$ django-admin startproject django_api

Let's create a Django application for this project (If you need a refresher on the difference between a Django project and a Django application, check this Stackoverflow answer):

We will call our application main:

$ python django_api/manage.py startapp main

We are now ready to add code to our Django application.

The Django API code on the main app

We will have a Person model, and we will code a simple view using Django Rest Framework to create instances of this model.

models.py:

from __future__ import unicode_literals

from django.db import models


class Person(models.Model):
    name = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name

In views.py we have:

from rest_framework.views import APIView
from rest_framework.response import Response

from .models import Person
from .serializers import PersonSerializer


class PersonViewSet(APIView):

    def post(self, request):
        Person.objects.create(name=request.data['name'])
        return Response(PersonSerializer(Person.objects.all(), many=True).data)

We are just using an API endpoint to do POST requests. We are also using a serializer for our model Person that is used by the view to return some data about the Person. The code is on the serializer.py:

from rest_framework import serializers

from .models import Person


class PersonSerializer(serializers.ModelSerializer):

    class Meta:
        model = Person

and to expose our endpoint we need some code in the urls.py file:

from django.conf.urls import url

from .views import PersonViewSet

urlpatterns = [
     url(r'^api/person/', PersonViewSet.as_view(), name='person'),
]

and include the main app URLs on the project URLs.

Add the snippet url(r'', include('main.urls')), to the urlpatterns so that URLs from your project be included in the application. For more details about it see here.

Finally we also need to set up the main app, the Django Rest Framework, and django-cors-headers on the settings.py, so add 'main', 'rest_framework', and 'django-cors-headers' to the settings INSTALLED_APPS list. See here how to do it if you have any doubt.

Check on the django-cors-headers set up doc to see why we added this:

'corsheaders.middleware.CorsMiddleware', to our MIDDLEWARE_CLASSES, and CORS_ORIGIN_ALLOW_ALL = True on our settings.py.

And that's all on the back-end code.

The code for the front-end

As on our blog article, we are storing it on a directory we called www:

$ mkdir www

and there we will have our file index.html which is very simple:

<!doctype html>
<html>
...
  <script data-main="js/start" src="js/require.min.js"></script>
...
  <div ng-controller="mainController">
      <h3>Person:</h3>
        <form name="personForm">
            <input
             type="text"
             name="personName"
             required
             ng-model="person.name"
             placeholder="Enter a name here"
             ng-class="{error:personForm.personName.$error.required}">
            <button
             id="button1"
             ng-disabled="personForm.personName.$invalid"
             ng-click="add_person(person.name);">
             Add person
            </button>
        </form>

      <div>
          <hr>
          <h1>Persons</h1>
          <ul>
              <li ng-repeat="person in persons">{{ person.name }}</li>
          </ul>
      </div>
    </div>
  </div>
...
</html>

We define some styles there, a form, some AngularJS code needed to do the server request, and to show some data that comes from the server. This .html file, and also the JavaScript file it references, should be stored at an electric domain. We will describe the corresponding devlove.yaml file in a bit.

You will need AngularJS v1.4.7, and RequireJS 2.1.22, but they are also included in our project repository.

We have also a couple of JavaScript files there, start.js which uses require to export Angular, and set our Angular app ready to use on the the index page:

require.config({
    shim: {
        'angular.min': {
            exports: 'angular'
        }
    }
});

define(["app/mainController", "angular.min" ], function(mainController, angular) {

    angular.element(document).ready(function() {
        angular.bootstrap(document, ["myApp"]);
    });

});

and the mainController.js where we have some Angular code to do a POST request to our API, and bring some data from the database to show on the index page as well:

define(["../angular.min"], function(angular) {

    angular.module('myApp', [])
      .controller('mainController', ['$scope', '$http', function ($scope, $http) {
          $scope.add_person = function(name) {
                $http.post(
                    'https://api.httpdos.com/api/person/',
                    {'name': name}
                ).then(function(response) {
                    $scope.persons = response.data;
                });
          }
      }]);

});

This custom source scripts go at the www/js and www/js/app folders respectively.

Take note of the domain to which we make the POST request. We will be running the Django API end-point behind that host name. But thanks to the magic of SOCKS5, there is no need to worry about configuring that domain name.

The server configuration file

In the root of your directory, create a text file named devlove.yaml with the following contents:

---
shimmercat-devlove:
    domains:
        www.httpdos.com:
          root-dir: www
        api.httpdos.com:
          port: 8080

In the example above, note the use of the website names, the root directory www for the electric domain, and the port number.

The contents of this file describe two virtual domains. The first one, www.httpdos.com is the electric domain holding your application assets, and the second one is the API domain where you put the Django application to listen.

Running the back-end and the server

You need to run ShimmerCat and your application simultaneously. In a production environment you would probably want to use some kind of application supervision program, but for development one of the most straightforward ways to go is to use two terminals. Just be sure to have both terminals at your project folder (we named it django_example_code at the beginning of this guide).

You can see more details here: https://github.com/shimmercat/django_example_code, about how to set up the server and the client.

In one of the terminals you leave ShimmerCat running:

$ shimmercat devlove

in the other you run your Django application:

$ python django_api/manage.py runserver 8080

Accessing the new site

Now you can fire a browser, e.g., Chrome:

$ sc-tool chrome

and in the browser's navigation bar, just type (please beware of the "https://" prefix!) https://www.httpdos.com and press ENTER. If you want to understand better what we are doing, you can check our page on easy networking (for developers) with a SOCKS5 proxy.