Manage Django URLs for AngularJS¶
AngularJS controllers communicating with the Django application through Ajax, often require URLs, pointing to some of the views of your application. Don’t fall into temptation to hard code such a URL into the client side controller code. Even worse would be to create Javascript dynamically using a template engine. There is a clean and simple solution to solve this problem.
Note
Until version 0.7.14 django-angular reversed all existing URLs of a project and created an object exposing them to Javascript. Documentation for now deprecated approach is available here.
Starting with version 0.7.15, django-angular provides a new way to handle URLs, which offers the reversing functionality directly to AngularJS modules.
This service is provided by djangoUrl.reverse(name, args_or_kwargs)
method. It behaves
exactly like Django’s URL template tag.
Basic operation principle¶
django-angular encodes the parameters passed to djangoUrl.reverse()
into a special URL
starting with /angular/reverse/...
. This URL is used as a new entry point for the real HTTP
invocation.
Installation¶
Angular¶
- Include
django-angular.js
:
<script src="{% static 'djng/js/django-angular.js' %}"></script>
- Add
djng.urls
as a dependency for you app:
<script>
var my_app = angular.module('MyApp', ['djng.urls', /* other dependencies */]);
</script>
The djangoUrl
service is now available through dependency injection to all directives and
controllers.
Setting via Django Middleware¶
- Add
'djng.middleware.AngularUrlMiddleware'
toMIDDLEWARE_CLASSES
in your Django
settings.py
file:
MIDDLEWARE_CLASSES = (
'djng.middleware.AngularUrlMiddleware',
# Other middlewares
)
Warning
This must be the first middleware included in MIDDLEWARE_CLASSES
Using this approach adds some magicness to your URL routing, because the AngularUrlMiddleware
class bypasses the HTTP request from normal URL resolving and calls the corresponding view function
directly.
Usage¶
The reversing functionality is provided by:
djangoUrl.reverse(name, args_or_kwargs)
This method behaves exactly like Django’s URL template tag {% url 'named:resource' %}
.
Parameters¶
name
: The URL name you wish to reverse, exactly the same as what you would use in{% url %}
template tag.args_or_kwargs
(optional): An array of arguments, e.g.['article', 4]
or an object of keyword arguments, such as{'type': 'article', 'id': 4}
.
Examples¶
A typical Angular Controller would use the service djangoUrl
such as:
var myApp = angular.module('MyApp', ['djng.urls']);
myApp.controller('RemoteItemCtrl', ['$scope', '$http', '$log', 'djangoUrl', function($scope, $http, $log, djangoUrl) {
$scope.loadItem = function() {
var fetchItemURL = djangoUrl.reverse('namespace:fetch-item');
$http.get(fetchItemURL).success(function(item) {
$log.info('Fetched item: ' + item);
}).error(function(msg) {
console.error('Unable to fetch item. Reason: ' + msg);
});
}
}]);
and with args:
$http.get(djangoUrl.reverse('api:articles', [1]))
or with kwargs:
$http.get(djangoUrl.reverse('api:articles', {'id': 1}))
Additional notes¶
If you want to override reverse url, e.g. if django app isn’t on top level or you want to call another server
it can be set in .config()
stage:
myApp.config(function(djangoUrlProvider) {
djangoUrlProvider.setReverseUrl('custom.com/angular/reverse/');
});
Warning
The path of request you want to reverse must still remain /angular/reverse/
on django server,
so that middleware knows it should be reversed.