Thursday, January 2, 2014

Year 2014

Our baby is out in the world! We are still keeping her under wraps but it has happened. And now the journey from MVP to MVP. From Minimum Viable Product to Most Valuable Product!

Monday, October 14, 2013

Automatically create super user when running syncdb

MVP of the new world changing app is getting sculpted, you are still some weeks away from using migrations (aren't we always) and DB gets deleted even before it has time to say hello to it's neighbors on the disk, only to be recreated with another set of tables. Well, it is all fine and dandy for syncdb is smooth as silk expect for that annoying prompt to create super user! If I had a customer for every time I typed in admin/admin/admin/admin on terminal, I would receive VC funding faster than I can say funding.

But since we are not even getting a feature done leave aside getting a customer by doing this boring shit, here is how you get rid of it. You use fixtures. Next time you have created the super user, dump the auth tables thus:
$ django-admin.py dumpdata auth > initial_data.json
And next time run syncdb like this:
$ django-admin.py syncdb --noinput

And it is smooth as a chin shaved with Gillette Mach 3. Or Philips if that is what you prefer.

For better organization, do not forget to move it to a fixtures directory and add that directory to FIXTURES_DIR variable in settings.

Happy DB deleting!

Credits: Stackoverflow

Wednesday, September 25, 2013

Supporting IP address ranges in Django Internal IPs setting

Django internal ips is one of those pesky little details that turn out to be the reason for your css not loading in your web app after you restarted your machine. Here is the chain of events:

Restart -> DHCP -> IP change -> no longer an internal IP -> DEBUG is false -> your templates render as if on production -> you need css instead of less.

Unfortunately internal_ips can only take individual IP addresses and not a range. So if you decide to package your app into a nice vagrant VM for distributing to your colleagues, when they run and try to access it, again the same problem.

Solution is simple. After all it is Python we are talking about. :)

Inspired by http://dancarroll.org/blog/2011/01/debugging-django-dev-server/, I included a container derived from list that answers yes to the membership question whenever the given key matches one of the patterns in the list.

from fnmatch import fnmatch
class globlist(list):
    def __contains__(self, key):
        for pat in self:
            if fnmatch(key, pat): return True
        return False
# Put the whole internal range as internal ips
INTERNAL_IPS = globlist(['127.0.0.1','192.168.1.*'])

Voila!

Sunday, June 16, 2013

HATEOAS

Got one version of the HATEOAS working but it doesn't look like it will go very far.

Basically while initializing the collection of pages in a publication, I do it manually and use the URLs provided by the API to set the URL on each of the pages model. Later when a publication is requested, I trigger the fetch on all the page models.

The problem is there are usually a lot of pages and all these calls take time. It looks funny when the starting view contains the default title for all the pages and slowly they are replaced by the actual title as they are loaded. I think it would be a better experience to show only few pages to start with and keep populating the list as additional pages are loaded. Perhaps it is better to modify the API or ignore the pages URL all together.

Saturday, June 15, 2013

Handling HATEOAS with Marionette

Till few days ago, I was an innocent web developer building a REST API. Then I came to know about HATEOAS and my life was never the same again.

HATEOAS essentially means that the API consumer should be able to navigate the API simply on the basis of information provided by the API and should not require out of band information. One example is the end point discovery. When you fetch resource A that is related to several instances of resource B, the url to API endpoints for resource B should be included in the server response.

Currently my Publication object returns with the links for its constituent pages. Now I am trying to figure out the best way of taking these URLS and using them in backbone to load the individual pages.

Next week's aim is to spend time on Page editor and finally get the template thing working. Finally we are coming to the point of this whole exercise. Warm up is done and the real play begins!

Friday, June 14, 2013

Bootstrap tabs in a Marionette view

Not much progress today but after couple of blind alleys, managed to get the bootstrap tabs working in a Marionette Layout. It mostly works out of the box since there is no removing elements from the dom business here unlike modal dialogs. So you just wrap the jquery plugin for use in rjs and then correctly markup the html in template.

Thursday, June 13, 2013

PushState, RequireCSS and RequestResponse

Today was the day of lots of new things. As I mentioned yesterday, I was in the market for something that will help me load my CSS.

While I agree that requirejs is a great tool to manage js dependencies, lately I am feeling that it leaves the job half done. A modular piece of JS, in many cases, will come with accompanying CSS and html templates. For example, almost every jquery plugin has a JS and a CSS file. Requirejs provides no API for declaring dependency on a whole module.

One way to achieve this with rjs is as following. First find a rjs plugin that loads html templates and css. Then write a wrapper module declaring dependency on both js and css. Now use this wrapper module wherever you needed the original. But this means writing a wrapper for every plugin or library you want to use. Given that rjs wants one module per file, this can mean a lot of files! One way of working around that is:

define('external', [], function() {
    var exports = {};
    exports.plugin1 = {
      ...
    };

    exports.plugin2 = {
      ...
    };

    return exports;
});
Then we can add a dependency on 'external' and use the required module. But now every external module will be loaded as a dependency for your module which is again not very palatable.

Loading CSS using RequireJS

For loading CSS, there are some plugins available. The primary issue is that a lot of modern browsers seem to be lacking a onload event on link elements. This means while it is easy to add a link element in the dom and thus load the CSS, there is no way to know when the sheet has loaded. One workaround is to keep polling the dom stylesheets to see if the new sheet has come in. The other approach is more clever. You create a script tag and use the css url as src. Browser loads the css and tries to interpret as a script and throws an error. So the onerror event on script tag can be treated as the onload for the css file.

There are bunch of drawbacks. One is that onerror gets called for 404 errors also. This means that the sheet was not found. This can be overcome with checking for the presence of stylesheet in the dom.

The other issue is that invalid script tag throws errors in the console. The workaround for that is to use img tag instead of script tag. With img tag, there is a non-threatening warning in the console and that's it.

There are couple of rjs plugins available that implement the above ideas: RequireCSS & CSSLoader. I am using a fork of RequireCSS that uses the img tag technique described above.

RequestResponse

RequestResponse is a simple object on which you can do two things:
  • set handlers for particular requests by name
  • make a particular request. The handler for the request will be executed and response returned.
Marionette applications come with a RequestResponse object on them. One use I am making of them is to make a central datastore for my models and collections. All other parts of application request the data from this central place. Updates are also done in the datastore. Other components use events to indicate what needs to be done.

This means any changes to a model or collection are immediately propagated to all the views. It also helps in supporting both the option of getting data: through a bootstrap variable dumped by the server in initial file or through a fetch from server.

// datastore module

var store = {};
// The library for the current user
function getLibrary(){
 if(!store.library){
  if(typeof pubs === 'undefined'){
   store.library = new Library();
   store.library.fetch();
  }
  else{
   store.library = new Library(pubs);
  }
 }
 return store.library;
}

var reqres = new Backbone.Wreqr.RequestResponse();
reqres.setHandlers({
 "collection:library": getLibrary,
 "model:publication": getPublication
});

return reqres;


// using the datastore in a view
// Request the library collection to be displayed
this.collection = DataStore.request("collection:library");

This pattern is useful when trying to build support for pushstate in your application. In case of pushstate, the view can either be rendered directly from the server or it might be reached through some interaction on the frontend. If the view is being rendered on the server side, it makes sense to provide the bootstrap data along with the template thus avoiding a extra call for data fetch. On the other hand, if we reach the view through some frontend interactions, we have to fetch the data from server through an AJAX call. A central datastore encapsulates the logic of doing the right thing in both the cases.