Django

Beginner Troubles with Django and AngularJS

The marriage of Django and AngularJS theoretically is a pleasant one. The ceremony looks promising and the ‘lived ever after’ is a great one. Yet, initial preparations for this marriage doesn’t really go that well, considering Django is server-side framework basically, and AngularJS plays its game in the client-side.

Although this provides amazing ninja capabilities at the front-end, with a kung-fu defender patrolling the servers, and issuing great performance, it can be a challenge to get started.

In this short article, lemme tell you about two items to purchase and get ready for the marriage ceremony. First, you’ll need to let AngularJS routing and Django’s embrace. Yep, sit them down, tell them the rules (or play around the rules) and let peace prevail.

The next is a simple tweak, to get clean URLs in your app. I can confidently say, that without clean URLs in Django, then there’s NO Django! Says Django (making a bit of fun at PHP and filename trails on web pages)

A clean, elegant URL scheme is an important detail in a high-quality Web application. Django lets you design URLs however you want, with no framework limitations. There’s no .php or .cgi required, and certainly none of that 0,2097,1-1-1928,00 nonsense.

Hahaha… ha. ha, well jokes aside, that’s true. Those URL endings are ‘nonsense’. By default, Angular comes with such nonsense. We’ll blow that out of the water in this article with a simple tweak, from Angular itself.

Let AngularJS and Django Talk!

Communication is key to settling any form of dispute. Mingling two giant frameworks who rule their territories requires communication, in an amicable way.

This approach we’ll be considering deals with letting AngularJS find where to load templates, or ‘partials’ (repeating, reusable smaller templates used on bigger templates).

Angular is great for single-paged apps. Django isn’t great in that respect, considering communication goes back and forth with the server.

Django’s URLs are of the form:

....
    url(r'^my-url/$', views.myView.as_view(), name='my_view'),
....

But, because AngularJS works on the front-end primarily, in the client, the request to load pages doesn’t hit the server, thus wiring up routes in Django wouldn’t make any sense.

And because of this, it’s cumbersome trying to let Angular load its templates from the same directory as Django does. But there’s a way to get things going.

Get a URL route in Django that loads the base file of your Single page app, of course, from the Templates folder, then let Angular handle the rests.

# urls.py 
....
  url(r'^$', views.homepage, name='index'),
....

# views.py
def homepage(request):
 return render(request, 'index.html')

So consider this project structure. Your project is called Hello. In your project, you’ve got the app called main.

In your main app folder, you have the templates and static folder. You already know what goes where, right? If you don’t follow the quick tutorial from Django to familiarize yourself with the Project and App structure being discussed.

In the static folder, I put my pages in the folder /pages, to prevent scattering of partials and templates all over, since the static folder is also home to my static files (the .js and .css etc)

In your templates folder, you have ‘base.html’, or ‘index.html’. This file will look like this:

{% load static %}
<!DOCTYPE html>
<html ng-app="myApp">
<head>
  <title>Homepage</title>
  <script type="text/javascript" src="{% static 'js/angular.min.js' %}"></script>
  <script type="text/javascript" src="{% static 'js/angular-route.js' %}"></script>
 <script type="text/javascript" src="{% static 'js/myangular.js' %}"></script>
  <base href='/'></base>
</head>

<body>
<div ng-view></div>
</body>
</html>

Now, if you’re familiar with Django templates, the above index.html wouldn’t send you to coma. We loaded the static template tag, to be able to use in referencing our resources, i.e the angular.min.js and the angular-route.js into our templates.

The only weird part is the <div ng-view></div>, which I’ll explain in a bit. The above snippet doesn’t do much. So let’s let it do much then.

[wp_ad_camp_1]

The last referenced resource in the above index.html file is where we’ll hold the sense of code to help our HTML know where to load what. The ng-view is responsible for being the end point where, depending on context, or what page we’re on, the controller we’re about to write will feed in the ‘partials’.

So, myangular.js can look something like this:

// Create your myApp module
var myApp = angular.module('myApp', ['ngRoute']);

angular.module('preachApp')
// configuring routing.
.config(function($routeProvider, $locationProvider) {
    $routeProvider
        .when('/', { // If URL is at /, uses template at
            templateUrl: '/static/pages/home.html', // this location
            controller: 'homeController' // and apply instructions from this controller
        })

    .otherwise({ // Any other URL, take me back to /
        redirectTo: '/'
    });
});

At this point, our code is getting a bit bigger. The workflow is this:

  • A user comes to our homepage, say, blog.khophi.co
  • The URL configuration specified in URLs.py in our Django earlier takes the user to the template file we specified in the views.py
  • That template is ‘angularized’, and on the front-end, at the client-side, Angular kicks in its OWN routing too. You can call it ‘The Second Routing!’
  • This routing is simple: When you realize you’re on the ‘/’ page, which is the root page, go looking for the file, ‘home.html’ in the folder, ‘/static/pages/’.
  • Django also loads statics from that folder, and as such, allows the world to access that endpoint, including our Angular, therefore Angular doesn’t hit a bummer trying to load that template
  • The home.html template (or partial, whatever), when loaded, is appended to the current index.html (which was loaded from server-side by Django and served) to form a complete page.

Running the above marriage ceremony like that might throw up unwanted balloons here and there, thus, let’s get the homeController setup to ensure we’re good to go, and Angular will find that controller to apply to the page when its done loading.

Which can look like this:

var myApp = angular.module('preachApp')

myApp.controller('homeController', function($scope) {
    $scope.message = 'I am the homepage';
});

This all might sound a lot to take in, but just breath in, and out! We’re just trying to make the communication happen, the one we talked about earlier. So, with that set, we should be able to get Angular and Django playing nice when it comes to URLs.

Don’t worry, the scattered snippets above are put into one, to help you get a cleaner look, although I prefer keeping parts of my app separated into specific files with specific jobs, like controllers.js, configures.js and I do what it’s called the Dependency Injection in areas I need to.

LogECG was built using Django

Ugly URLs

No one likes it, yet they prevail online to this day. But we can help stop it, by using clean URLs, like this: localhost:8000/mypage, instead of localhost:8000/#/mypage

To do so, Angular comes with a simple, useful addition, like this:

myApp.config(function($locationProvider) {
    $locationProvider.html5Mode(true);
});

The above can be in your configure.js file, which holds every possible code responsible for configuring your app, and this is one of the configurations – $LocationProvider.

The /#/ in links might not be that embarrassing compared to the trailing file formats i.e .php or .cgi, but I’ll recommend you get rid of them. No /#/ in URL is better.

Conclusion

So what have we achieved so far? Lemme put them all into a single .js file to make things easier to follow at this point, at least, a nutshell you can take home.

// Our myangular.js 
var preachApp = angular.module('preachApp', ['ngRoute']);

preachApp.config(function($locationProvider) {
    $locationProvider.html5Mode(true);
});

preachApp.config(function($routeProvider, $locationProvider) {
    $routeProvider
        .when('/', {
            templateUrl: '/static/pages/home.html',
            controller: 'homeController'
        })

    .otherwise({
        redirectTo: '/'
    });
});

preachApp.controller('settingsController', function($scope) {
    $scope.message = 'I am on settings page';
});
<!-- Our index.html -->
{% load static %}
<!DOCTYPE html>
<html ng-app="myApp">
<head>
  <title>Homepage</title>


  <script type="text/javascript" src="{% static 'js/angular.min.js' %}"></script>
  <script type="text/javascript" src="{% static 'js/angular-route.js' %}"></script>
  <script type="text/javascript" src="{% static 'js/angularscript.js' %}"></script>
  <base href='/'></base>
</head>

<body>
    <div ng-view></div>
</body>
</html>
<!-- Our home.html -->
<div ng-controller="homeController">
{$ message $}
</div>

Hit the web for more info on AngularJS and Django. But wait, why is the tag {$ message $} being used, instead of Angular’s {{ }} tags?

Will cover that in a subsequent post on Beginner Troubles with Angular and Django!

 

Related Articles

Back to top button