Integrate AngularJS with Django

XMLHttpRequest

As a convention in web applications, Ajax requests shall send the HTTP-Header:

X-Requested-With: XMLHttpRequest

while invoking POST-requests. In AngularJS versions 1.0.x this was the default behavior, but in versions 1.1.x this support has been dropped. Strictly speaking, Django applications do not require this header, but if it is missing, all invocations to:

request.is_ajax()

would return False, even for perfectly valid Ajax requests. Thus, if you use AngularJS version 1.1.x or later, add the following statement during module instantiation:

var my_app = angular.module('MyApp').config(function($httpProvider) {
    $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
});

Template tags

Django and AngularJS share the same token for variable substitution in templates, ie. {{ variable_name }}. This should not be a big problem, since you are discouraged to mix Django template code with AngularJS template code. However, this recommendation is not viable in all situations. Sometime there might be the need to mix both template languages, one which is expanded by Django on the server, and one which is expanded by AngularJS in the browser.

The cleanest solution to circumvent this, is by using the verbatim tag, which became available in Django 1.5.

A less clean solution, is to change the syntax of the AngularJS template tags. Just add the following statement during module instantiation:

var my_app = angular.module('MyApp').config(function($interpolateProvider) {
    $interpolateProvider.startSymbol('{$');
    $interpolateProvider.endSymbol('$}');
});

Now, you can easily distinguish a server side variable substitution {{ varname }} from a client side variable substitution {$ varname $}.

This approach is less verbose than using the verbatim tag. The problem, however, is that you have to remember to use this alternative tag syntax for all of your AngularJS templates. It also makes it difficult to integrate third party AngularJS directives, which are shipped with their own templates.

Partials

In AngularJS, when used together with external templates, static HTML code often is loaded by a `$templateCache`_. These so named partials can be placed in their own sub-directory below STATIC_ROOT.

If, for some reason you need mixed template code, ie. one which first is expanded by Django and later is parsed by AngularJS, then add a view such as

class PartialGroupView(TemplateView):
    def get_context_data(self, **kwargs):
        context = super(PartialGroupView, self).get_context_data(**kwargs)
        # update the context
        return context

Resolve this view in urls.py

partial_patterns = patterns('',
    url(r'^partial-template1.html$', PartialGroupView.as_view(template_name='partial-template1.html'), name='partial_template1'),
    # ... more partials ...,
)

urlpatterns = patterns('',
    # ...
    url(r'^partials/', include(partial_patterns, namespace='partials')),
    # ...
)

By using the utility function

from djangular.core.urlsresolvers import urls_by_namespace

my_partials = urls_by_namespace('partials')

the caller obtains a list of all partials defined for the given namespace. This list can be used when creating a Javascript array of URL’s to be injected into controllers or directives.

Inlining Partials

An alternative method for handling AngularJS’s partial code, is to use the special script type text/ng-template and mixing it into existing HTML code. Say, an AngularJS directive refers to a partial using templateUrl: 'template/mixed-ng-snipped.html' during the link phase, then that partial may be embedded inside a normal Django template using

<script id="template/mixed-ng-snipped.html" type="text/ng-template">
  <div>{{ resolved_by_django }}</div>
  <div>{% verbatim %}{{ resolved_by_angular }}{% endverbatim %}</div>
</script>

or if the $interpolateProvider is used to replace the AngularJS template tags

<script id="template/mixed-ng-snipped.html" type="text/ng-template">
  <div>{{ resolved_by_django }}</div>
  <div>{$ resolved_by_angular $}</div>
</script>

Dynamically generated Javascript code

There might be good reasons to mix Django template with AngularJS template code. Consider a multilingual application, where text shall be translated, using the Django translation engine.

Also, sometimes your application must pass configuration settings, which are created by Django during runtime, such as reversing a URL. These are the use cases when to mix Django template with AngularJS template code. Remember, when adding dynamically generated Javascript code, to keep these sections small and mainly for the purpose of configuring your AngularJS module. All other Javascript code must go into separate static files!

Warning

Never use Django template code to dynamically generate AngularJS controllers or directives. This will make it very hard to debug and impossible to add Jasmine unit tests to your code. Always do a clear separation between the configuration of your AngularJS module, which is part of your application, and the client side logic, which always shall be independently testable without the need of a running Django server.

Bound Forms

AngularJS’s does not consider bound forms, rather in their mindset data models shall be bound to the form’s input fields by a controller function. This, for Django developers may be unfamiliar with their way of thinking. Hence, if bound forms shall be rendered by Django, the behavior of AngularJS on forms must be adopted using a special directive which overrides the built-in form directive.

To overrides the built-in behavior, refer to the Javascript file django-angular.js somewhere on your page

<script src="{{ STATIC_URL }}djangular/js/django-angular.min.js" type="text/javascript"></script>

and add the module dependency to your application initialization

var my_app = angular.module('myApp', [/* other dependencies */, 'ng.django.forms']);