Showing posts with label django. Show all posts
Showing posts with label django. Show all posts

Tuesday, April 06, 2010

Django vs. Grails

When I came up with the Five Technologies in Five Weeks project, I hadn't intended to compare any of the technologies to each other directly.  My original ordering for the technologies didn't have any head-to-head match-ups, but I just finished my Grails project, which was "right after" (modulo interruptions) my Django/GAE project.  And, while I was working on Grails, I kept comparing it to Django, and I felt compelled to write up my observations.

"All things being equal, which they never are" (Manager Tools), I'd choose Django over Grails for a new, green-field project.  However, given the constraint to run in a Java environment, I'd gladly choose Grails over the other Java/J2EE frameworks I'm familiar with.  (Django on Jython would be a contender as would Wicket, but I don't have hands-on experience with either.)  This is not a slam on Grails.

Here are some of the reasons I prefer Django over Grails:
  • Development Speed (not runtime performance): running (a trivial number of) unit tests for Grails on my machine took about 15 seconds (with Folding@Home in the background).  Django unit tests typically only take me a couple of seconds (for a trivial number of tests).  Integration tests in Grails were 30-40 seconds; Django might be 5 seconds.  Although Grails will reload the running webapp when you make a change, sometimes things are really buggered, which requires a full restart.  That seemed to happen more often in Grails than Django, and restarts take ~20 seconds vs. 2 seconds.
    Compared to the 5-7 minutes I've seen WebSphere to restart an application, Grails is blazingly fast.  But the 15-30 seconds that many operations take in Grails is long enough for the mind to wander, which is not good.
    Update: a commenter pointed out the (under-documented) interactive mode of Grails.  That speeds the edit-test-edit loop considerably.
  • Voodoo: both Grails and Django do some voodoo behind the scenes to reduce the amount of chimp programming (e.g., non-DRY boilerplate) the programmer has to do.  This voodoo involves topics of the high priests like meta object programming that mere mortals typically don't have to worry about.  Maybe it's just that I don't have as much "time behind the wheel" with Grails, but I feel like its voodoo leaks out a bit and is too voodoo-rific.  A Grails programmer has to be aware of which methods are dynamically added to a class in order to separate unit tests (no voodoo) from integration tests (full voodoo). And, although I like the power of dynamic finder methods like User.findByName(), it kinda bugs me that the code for that doesn't exist somewhere that I can see (you know, on punch cards!)  You don't see the dynamic methods on a Django class, but there are a lot fewer of them, so it seems less voodoo-rific.  Again, maybe more time behind the wheel of Grails would make me feel more comfortable.
    (As an aside, when I taught Python and Django in Spring 2009, the students didn't even notice the voodoo of fields on models in Django until I pointed it out to them.  Then, I exploded their heads with MOP.)
  • View Technology: I have a long-standing personal preference for templates instead of ASP/JSP-like mark-up languages, and I'd lump Grails GSP pages in the latter category.  Back in the day, Jason Hunter wrote an essay called The Problems with JSP that really stuck with me.  GSPs are much, much better than the Model 1 JSP pages that Hunter talks about, but they still feel similar enough to make me think about using something like Velocity with Grails.  Django kicks templates up a notch by having inheritance with templates, which I really love. (Even if Django didn't invent template inheritance.)
  • Dynamic Language Issues: This is a real unfair comparison because I've been using Python for 15 years, but I felt that errors in Grails/Groovy were more cryptic and hard to find compared to Python.  If I typo the named parameter to a method in Python, it lets me know immediately.  More than once in Grails I misspelled a named parameter to a constructor, which failed silently and then lead to a validation failure later when I went to save the object.  Some of that is from lack of experience with Groovy/Grails - i.e., learning what error messages really mean.  But still, Python seems to fail in a more helpful way.  (I'd say Python fails gracefully, but if anything it's the opposite: very loud - "you dumb-ass, there is no parameter called recipent" when I misspelled recipient.)
I don't mean for this to be a hit-piece against Grails; I really like Grails.  I look forward to using it some more.  It's just that, for what it's worth, I like Django more.

Wednesday, March 24, 2010

5Tech - Week 1: Google App Engine

For the first of the five technologies in five weeks, I picked something easy - Google App Engine using Python and Django. As someone who's been using Python for 15 years, there was no language learning curve. And using the Django helper for app engine package allowed me to leverage my Django experience. So with a minimal learning curve, the results were basically all good.

The project involved creating a simple application to monitor web sites to check if they are up or down and notify the user about status changes. As such, the core of the application isn't even a web app. In fact, I've implemented the same thing a couple of different times as a standalone program in Python or Java. However, to run a standalone application like that requires a server where it can run, and that's not something I've always had access to. GAE's cron service provides the ability to run checks periodically - just like the main loop in my standalone applications, and GAE provides a large number of notification options, although I only used email initially. The application does have a web interface for configuring checks and viewing the status

Project Analysis

My biggest problem developing the application was the fact that I was working with three separate but overlapping tools/frameworks: GAE, Django, and the Django helper. These all worked fine, but when I wanted to do some task, I didn't know where to look for the "right" way to do it. After wasting a bunch of time searching for things only to find that the Django way was the right way, I just quit asking and adopted the "try Django first" strategy. And then, the first time I went to apply that I got burned - there are some slight differences in how the filter method is handled in Django helper versus "native" Django. But for the most part, Django first is the way to go. In addition to the online documentation for these three tools/frameworks , I used Programming Google App Engine by Sanderson, which covers all of them - I highly recommend it.

Although my plan with Five Technologies is to use best practices, I am embarrassed to admit that I didn't practice much test driven development on this project despite having "home field advantage" with the technology - Django. Some of that is due to the exploratory nature of the programming - just figuring out which end is up, and some of it was the confusion over how to do tests - as noted above, the answer is "the Django way". Also, I found a bug in the app engine helper when loading a fixture, which hung me up - I'll be submitting a patch shortly.

One (non-technical) practice that I adopted was the Pomodoro Technique, and that worked pretty well. The 25 minute mini-sprints were really nice to contain technology-induced ADD. However, the watch I was using as my timer died during a pomodoro which lead to a very long and productive pomodoro.

In terms of the bigger goals of Five Technologies, I have another confession: I did not restrict myself to one week. I created version 0.1 and deployed it to the cloud within one week, but the week following this project I went to the Java Posse Roundup, and I kept working on the Django app, even though I should have been focusing on Java. It's just that after a week of working on GAE, I had built up some good momentum and didn't want to quit. I fear that this will be a real problem for the next projects because I won't have the luxury of continuing to work on whatever technology when I begin the next project.

In conclusion, the first technology experiment was a success, even if I wasn't dogmatic. What's next? Most likely Grails. Stay tuned.

Update:  I forgot to mention something cool I learned about - schema migration, or the lack thereof.  Before I began the project I was fretting about schema migration on GAE because I've been too lazy to learn something like South, and therefore I do schema migrations at a SQL command prompt.  Obviously, there is no SQL problem for a NoSQL database like Google's BigTable.  Then I forgot about the issue, but half way through I looked up and said, "hey, I haven't been doing any migrations, but this all works."  Duh! -  like many NoSQL databases, BigTable is schema-less, so there is no schema to migrate.  Problem solved.  OK, the application has to be prepared to do with an attribute on a record/row that isn't present, but that code is basically the same as dealing with a NULL value that you might specify as the default value when you issue an ALTER TABLE to add a column.  Also, you can still imagine scenarios where you might still have to do some sort of schema/data conversion, but without even consciously thinking about it, I managed to avoid those.  That was cool.

Thursday, October 01, 2009

World's Ugliest URLs

I live outside the city of Monmouth, Oregon (beneath the Western Skies, of course). Our city's official website has URLs like:
http://www.ci.monmouth.or.us/index.asp?Type=B_BASIC&SEC={F6D36CB4-8AB1-4E2F-9F16-EEB14A3A83DD} - Things to See & Do
http://www.ci.monmouth.or.us/index.asp?Type=B_BASIC&SEC={6010A930-F666-42AF-A359-971AC53933A1} - City Government

OK, maybe they're not the ugliest in the world, but those bad boys have gotta rank way up there. Anyway, when I first heard Jacob Kaplan-Moss talk about pretty URLs in Django, I thought some of criticisms were a little nit-picky. Initially, I didn't see anything wrong with index.php, but I could see the basic point even before seeing Monmouth's URLs. When I converted the Evergreen Terrace Farms site from PHP to Django, cleaning up the URLs was something I was pleased with. For example, www.et-farms.com/animals/detail.php?name=bart became www.etfarms.com/animals/bart. So, I guess I have drunk the Kool-Aide, and I have become a bit of a URL snob.

Regardless of how picky you are about URLs, I think any sane person would agree that those URLs for the Monmouth site are just crazy. Just imagine trying to read one of those to your mom over the phone - "no, it's 42AF, and the A and the F are capitalized."

In my opinion, the saddest thing is that the site is a commercial product created by a company that boasts about how many governments they've sold it to. It would be one thing if some students created something like that for a senior project, but when you're charging people money for something like that you should at least not expose the ugliest of the ugly Microsoft crap from the depths of the implementation (I assume those are UUIDs generated by .Net). I guess I'm also disappointed that no one in the city even noticed those URLs before putting out taxpayer money.

Charles.

Monday, June 01, 2009

404 Errors with Django flatpages

In a Python class I'm teaching, I had the students do the Django tutorial with some added bits. One of the added bits was to add an About page using Django flatpages. A couple of students had problems where they were getting 404 errors even though there was a flat page defined at the /about/ URL.

I had one student zip up his project (including his sqlite database) and send it to me. (One of the other "added bits" was that they had to create portable projects - no hardcoded paths in settings.py.) When I first ran his project, sure enough - 404. I poked around, and everything looked good. Then, I used manage.py loaddata to load my data (including a flat page) into his DB, and it all worked fine. So, it was a data issue, not a project-level mis-configuration.

After reading a comment from another student about this problem, I looked into the database using SQLite Manager, where I could see that the flat page was assigned with site_id #3, not the default #1, and somewhere along the line he had created multiple sites in his DB. I looked in settings.py, and sure enough, SITE_ID referred to site #1, not #3 As noted in the flat pages docs, this needs to match (under some circumstance). Changing that, fixed it all up with the students original data.

If you have been having this problem, I am hopeful that the Google sent you here, and you can see how to fix it.

enjoy,
Charles.

Wednesday, March 04, 2009

Book: Pro Django

Pro Django by Marty Alchin
ISBN: 978-1-4302-1047-4

Pro Django is an excellent book on Django, but it's not for beginners. The term "Pro" gets thrown around a lot, and it gets applied to things that might better be described with "Dummies." This is the Real Mc Coy - it's serious advanced stuff.

The chapters are centered around nice little chunks of the Django system: Models, Views, Forms, Templates, etc. Each chapter is a nice, self-contained bit of Django knowledge, except for Chapter 2, which is a great survey of advanced Python like meta classes. Most chapters also include an Applied Techniques section which gives some examples of how to apply the material in the chapter.

While reading this book, what struck me was how the chapters seem to pack in a level of detail that you'd typically find only in a comprehensive reference, but yet this book is not a bunch of dry reference material, or worse yet, copies of online manuals. The reader gets serious detailed information, but it almost reads like a fluffy tutorial. It's pretty remarkable.

Something that's unique about this book at this time (Q1 2009) is that it covers the 1.0 version of Django. A bunch of the first books on Django were written against 0.96 or earlier. You'd think there wouldn't be much difference (0.04 versions if you only look at the numbers), but the jump to 1.0 was significant for Django. It's nice to have a book that reflects the 1.0 world.

enjoy,
Charles.

Sunday, July 06, 2008

Converting a Django Site to newforms-admin

Right after I learned about Django at OSCON 2006, I created a prototype to replace an existing PHP site. Due to various distractions, I haven't done much with that Django site since then and it never went live, but I've come back to it recently.

My first order of business was to upgrade from 0.95 to something modern. The first stop was to upgrade to trunk. Following the instructions on the Django site, I got it running on trunk and only had to change maxlength to max_length in my models.

Since, newforms-admin will be merging with trunk soon, porting to newforms-admin was my next step. I pointed my django install at my newforms admin svn tree and let it rip - i.e., I didn't bother reading any documentation or anything.
It blew up with a nasty-looking traceback that ended with this:

func(self, *args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'prepopulate_from'

A quick Google search turned up this thread on the Django Users mailing list. Five minutes of reading the newforms-admin wiki page and refactoring my code, and I was up and running. So, despite the ugly-looking traceback, it just wan't that bad.

Granted, my project is pretty small because I never had much time to work on it. However, all in all, the conversion process from 0.95 to the bleeding edge of newforms-admin was pretty painless.

Another happy Django user,
Charles.