How to make AngularJS and Django play nice together

In order to make AngularJS working as I wish in my Django app, these are the settings that I’ve adopted:

1. Differentiate Angular templates symbols from Django ones:

Both Angular than Django use doble curly braces to mark variables and/or expressions ({{ myVar }}).
In order to have the full control on how and by who our templates are rendered, I redefined the Angular interpolations signs in the config() method of my client app.

$interpolateProvider.startSymbol('{$');
$interpolateProvider.endSymbol('$}');

2. Change the default Angular Content-type header used in POST method:

Angular defines the “Content-Type” header as “application/json” for ajax POST, but Django doesn’t understand that content properly and as result, the POST data is not an object as we expect but rather a string! So, I modified the default content type as “application/x-www-form-urlencoded” (which is the format used by jQuery and other JavaScript libraries).

$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

3. Assign the CSFR token to each ajax call automagically

In Django templates we can use the tag {% csrf_token %} inside a form to print an hidden input containing the token. But when it comes to making an xhr post request, how can we pass the token in an effective and DRY manner? The answer I gave myself is to set a default http header for ajax calls containing the value of the token obtained by reading the session cookie (in this way this stuff is handle 100% by JavaScript).

$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;

Differently from points 1 and 2, this is done in the run() method, since $cookies is an Angular service and can’t be used in config() block (in that function only provider objects can be used).
In order to use $cookies we have also to import “angular-cookies.js” in addition to the base “angular.js“.

The final configuration is the following:

angular.module('myapp', ['ngCookies']).
    config([
    '$httpProvider', 
    '$interpolateProvider', 
    function($httpProvider, $interpolateProvider) {
        $interpolateProvider.startSymbol('{$');
        $interpolateProvider.endSymbol('$}');
        $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
    }]).
    run([
    '$http', 
    '$cookies', 
    function($http, $cookies) {
        $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
    }]);

UPDATE:

Starting from Angular 1.2, you have also to set default headers in order to use Django helper method is_ajax() in your views:

$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
  • Does it work even when I’m not loading my templates using view functions (Pure REST API based UI)?
    As mentioned in Django docs:

    Warning
    If your view is not rendering a template containing the csrf_token template tag, Django might not set the CSRF token cookie. This is common in cases where forms are dynamically added to the page. To address this case, Django provides a view decorator which forces setting of the cookie: ensure_csrf_cookie().

    But say I’m loading my angular app completely statically (say at example.com). And I’m getting all the data using angular resources (mapped to say, app.example.com) so, none of my templates are being loaded by django at all. How could I still implement CSRF? If not what could be the workaround?

  • Even if you have a 100% Angular interface you still have to use at least a Django view to render the first template (that will contains the main markup and static resources like js and css), you could use the ensure_csrf_cookie() in that view.

  • Yeah, realised it. Thanks :)

  • What IDE Options do you recommend for developing Django with AngularJS? Is it easy to design with Dreamweaver and porting over?

  • The best ide for Python/Django is PyCharm

  • Sublime is a great choice in my opinion, with rich plugins and snippets for both angular, and django via package control.

    http://www.sublimetext.com

  • Despite I use Sublime for fast prototyping, IT’S NOT AN IDE, it’s a text editor! There is an huge difference! An IDE provides a lot of features and tools that a software like Sublime doesn’t. For example: static code analysis, code refactoring, tests integration, auto code generation, code validation, integration with common frameworks (like Django), integration with documentation tools, integration with databases and other technologies, integration with version control system like GIT or Subversion, and MUCH MUCH MORE!!

  • Joel Crocker

    Angular provides support for cookie-supplied CSRF tokens; it will set the retrieved token as a header on non-cross-domain requests:
    see the Cross Site Request Forgery (XSRF) Protection section at http://code.angularjs.org/1.2.9/docs/api/ng.$http

    You can configure this support to use the cookie name and header name that Django expects. I would recommend using this feature instead of just adding the header yourself, as it ensures that cross domain requests do not have the header, which protects your against leaking your CSRF token to 3rd-party sites.

  • Nice tip Joel, thank you ;)

  • nwjlyons

    Thanks for the top about is_ajax().

  • i put the angularjs into a 2nd server, works well. using a cors headers library to allow the 2nd server. disabled csrf midle ware though, tried setting the token cookie on the header; no luck. need a secure way to talk to server, when i post data from angularjs it gets into request.body as a url encoded query string immaterial of passing and setting content type as json.

    article is good, must give integrating djangos templating with angularjs sometime but i always thought i ll use django only to handle data though its awesome to make quick websites.

  • gutovysk

    Hi! Great post. But is this used for mobile-app (using cordova+angularjs) and Django (as a server backend)?
    tks

  • No, this post was intended for “traditional” django web app, If you want to use angular on mobile I suggest you: 1. to use Ionic (http://http://ionicframework.com/) for the UI 2. to use django rest framework (http://www.django-rest-framework.org) to create REST services to be consumed by your mobile app 3. you don’t need to send data as “form-urlencoded” since in a REST scenario you can rely on default angular settings (which are thought to be used by sending json messages) nor you have to bother with interpolation signs (since the UI should be 100% on the client and the logic/services on the server)