5. 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.
5.1. Starting out¶
As usual, we recommend that you create a folder for your project
$ mkdir django_example_project
$ cd django_example_project
5.2. The back-end code¶
5.2.1. 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.
5.2.2. 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.
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.
5.3. 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.
5.4. 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.
5.5. 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
5.6. 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.