A Kinder Gentler Django
Lately I have been thinking a lot about how well Django adapts to new users. I noticed that there seems to be an influx of first-timers. Although these programmers come from a variety of backgrounds, there are some areas within the framework that consistently cause stumbling blocks. In a lot of ways it is part of the reason that I’ve devoted a segment of This Week in Django to the subject. So what can be done to make Django more new user-friendly?
Convention Over Configuration
The idea of convention over configuration was really brought home with the Ruby on Rails framework. At almost every opportunity Ruby on Rails provides a default convention. David Heinemeier Hansson, the creator of Rails, calls it “Opinionated Software.” It definitely is opinionated. So much so that in some cases it is the reason why people do not embrace the framework. I’m not suggesting that Django does “convention over configuration” to the same extreme that Ruby on Rails does, but there are things that can be learned from Rails.
Sensible Settings
So what sort of things am I talking about? First, as an example, the ADMIN_MEDIA_PREFIX should default to something other than /media/. Most new developers to Django want to put their media at, well media. And as a result they end up having trouble serving up the Admin’s media files. So you say, there’s nothing stopping them from changing one or the other. Sure they can change the defaults, but that is not going to be their first response. Instead they are going to spend a lot of time trying to figure out why it does not work. So if the ADMIN_MEDIA_PREFIX was something like /adminmedia/ by default this would cause a lot less confusion.
“The whole global_settings.py is about defaults!” you say. So am I being nit-picky? Sure I am. I want Django to be the best damn framework on the planet. Plus, this post is not about ADMIN_MEDIA_PREFIX, it is really about making Django more palatable to new users. A good exercise would be to go through all the default settings and really think about them from the standpoint of a new user. For instance, should the TIME_ZONE information be pulled from the system environment? In some cases, perhaps we just need better documentation. In other words there’s not a sensible default, but perhaps we could clear up areas of confusion around the differing possibilities.
A Place for Everything
The other area where Django could could use some more convention is in “where things go”. The most often asked question about NewForms has nothing to do with using NewForms or making NewForms work. The most often asked question is “Where should I put my form class?” Yes, for those of you familiar with Python and Django this seems ridiculous. You say, “It’s a python module, put it wherever you want!” And you’re right, but a lot of “newbies” to Django are “newbies” to Python. They are coming to Python through Django. In fact that the case for myself. Yet, none of these “newbies” are asking “Where do I put my views?”
So given the audience, “convention over configuration” makes a lot of sense and saves a lot of repeated questions around the same types of issues. Someone who is new to the framework doesn’t really have an opinion about what is best, but they generally want someone to tell them “this is the way to do it.” Therein lies the confusion.
So how can we accomplish that? I can think of two solutions.
First we can provide more templates when the startapp management command is used. This would work much in the same way as the views.py module template is provide. A blank module with some comments and perhaps an import or two.
So the positives of this approach are that it would answer the question. There would be a “place for everything and everything is in its place.” But the negatives are that, well “everything would be in its place.” So where does it stop? Do we provide a managers.py, feeds.py, and signals.py templates? I think Ruby on Rails overdoes it with all the structure and files. You end up with the opposite problem of not knowing where anything is—not sure if you’re using the right bucket for the right purpose. So there’s got to be a balance somewhere.
The second solution is to provide more generators, management commands, to create these things on an as needed basis. I like this approach much better because it makes it real easy to ask the framework “I need a form. Please create one for me.” As you get more experienced with the framework, and develop your own “best practices,” you may or may not continue to use the generators, but at least they are out of the way and available if you want them.
If these management commands were to take a note or two out of the play book of Ruby on Rails, they could end up being quite convenient. For instance, there could be a management command that looks like:
./manage.py create form appname FormClassName
This could generate the forms.py module in the appname specified, where it has the FormClassName defined with all the correct imports. Likewise, we could have something like:
./manage.py create modelform appname ModelName
This would generate the forms.py module in the appname specified, with the ModelForm class defined and the inner meta for the model defined.
What Do You Think?
Clearly this is not going to be everyone’s “cup of tea,” but the great thing about this approach is that you don’t have to use it.
So, do you agree or disagree? Do you have other ideas about this “problem”, or do you think there is no “problem” to be solved in the first place? I look forward to hearing your thoughts, questions, criticisms.
