Django, Backbone, Handlebars

My whole programming career, I’ve defined myself as a back-end programmer. I know some javascript, but I feared CSS and the seemingly nit-pickyness of front-end coding.

Presently, I’m  building my own site for PinTheParty, and I *really* don’t want to bring another developer into the mix. I need to figure out how to do this on my own. I also need to redefine myself as a full-stack developer.

I’ve decided to use Python/Django with Backbone.js and Handlebars. There are many blog posts about bringing these and other frameworks together. But nothing exactly the way I wanted to do it. So I’m documenting my setup here.

      • First: Build the HTML page, including a template to use with Handlebars
        The venue_list div is where we will inject our rendered html from a Handlebars template. I’m also showing the js includes at the bottom. I’m using a library called ‘require’ to help organize all the js dependencies. This way, I don’t need to include all the js in the html, I can refer to it in each html’s supporting js file.
      • <div class="col-md-7">
             <div class="row search-results">
                 <div class="entry-searching-header">Searching "bake cupcakes"</div>
                 <div class="entry-header">25 results</div>
                 <div id="venue_list">
        
                 </div>
             </div>
         </div>
        ....
        <script data-main="/static/scripts/main" src="/static/scripts/require.js"></script>
        <script src="/static/scripts/venues.js"></script>
      • Second: Build the template contents using Handlebars tags in mark injection points.
        {{#each venues}}
        <div class="entry">
          <div class="row">
            <div class="col-md-6">
              <div class="entry-title"><a href="/venue/{{slug}}">{{name}}</a></div>
              </div>
            <div class="col-md-3 entry-cost">{{cost}}</div>
            <div class="col-md-3">
              <img alt="" src="/static/imgs/gograph_blue_ribbon.jpg" width="12px" />
            </div>
            <div class="row">
              <div class="col-md-12">
              <div class="entry-category">{{categories}}</div>
              <div class="entry-quote">{{quote}}</div>
            </div>
        </div>
        {{/each}}
      • Third: Build the supporting Backbone Model, Collections and View.
        I used one file to contain the Model, Collections and View to keep things simple. Notice, this is also where I use the require library at the top to help include required js dependencies, such as Backbone!  There are a couple choices I made.

        • I’m using an api to deliver the json
        • I fetch the data for the collection when it is first initialized. Because this is an asynchronous call, I need to make sure the template is injected when the data arrives. This is accomplished by setting “reset : true” in the call to collection.fetch and binding the render function call to the reset event. (By default the fetch will call “add” for each item in the json array)
        • When a collection receives json data and populates the associated models it expects an array of items. This is what I’m returning from the /api/vi/venues call. However the Handlebars syntax I’m using, {{#each venues}}, expects a parent element. So I add “venues:” when I pass the json to the template
        • There are two require blocks at the beginning of the file. The inner, nested require block is to include all the dependencies for this js file. The outer, require block is to load min.’s — the configuration file for require.js . Require.js recommends you use ONE main.js file to set the baseUrl as well as include js libraries that are used across the application. I don’t know if this is the best solution (nested require statements) but due to the way main.js is loaded (asynchronously using the data-main script attribute), I needed to make sure main.js is loaded before referring to its elements (i.e. backbone, underscore..)
require(['main'], function() {
	require(['jquery',
	        'underscore',
	        'backbone',
	        'handlebars',
	        'libs/text!../templates/parts/venue_list.html'],function($,_,Backbone,Handlebars,ListTemplate){

	    var Venue = Backbone.Model.extend({
	        defaults: {
	            name: 'My Favorite Place',
	            slug: 'my-favorite-place',
	            cost: '$$$',
	            quote:'Good for all ages with extremely helpful and competent staff!'
	        }
	    });

	    var VenueList = Backbone.Collection.extend({
	        model: Venue,
	        url: '/api/v1/venues',

	        initialize: function(){
	            this.fetch({reset:true,
		              success: function(collection, response) {
			          }
			    });
	         }
	    });

	   var venues = new VenueList;

	    var VenueListView = Backbone.View.extend({
	        el: '#venue_list',
	        // The collection will be kept here
			collection: null,

	        initialize: function(options) {
		        this.collection = options.collection;
			    // Ensure our methods keep the `this` reference to the view itself
			    _.bindAll(this, 'render');
			   this.collection.bind('reset', this.render);
			  },

	        render: function() {
		       var template = Handlebars.compile(ListTemplate);
		       var html = template({venues:this.collection.toJSON()});
		       this.$el.html(html);
	           return this;
	        }

	    });
	   	var myList = new VenueListView({
		      collection: venues
		});
	});
});
Advertisements

2 thoughts on “Django, Backbone, Handlebars

  1. oluwie

    Can’t wait for the site to go live. Sounds like a pretty neat idea. I checked out the blogpost site you have up for PinTheParty. Love the pics you put up 🙂

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s