(Also posted to pypap.blogspot.com.)
Back in April 2008 I eagerly volunteered to review a “rough cut” of Python Web Development with Django by Jeff Forcier, Paul Bissex, and Wesley Chun when I read of the opportunity on the BayPIGgies mailing list. I first completed a first version of this review in April (based on a version of the rough cut updated March 11, 2008). But I was asked to hold my review until it was updated again—I updated the review using the next two updates, but didn’t complete it. (I’ll post the whole sordid story is on yacitus.com.) I’m ashamed to say the book was published before I finished my review. (But I did post several comments on the rough cut—under the name “yacitus”—so I’m happy that I contributed to the final outcome in a small way.) I’m pleased to finally finish my review, about 10 months after I first read the “rough cut”. It’s fairly long, so you may want to skip to my recommendation in the third-to-last paragraph (before the footnotes).
Part II “Django in Depth” starts with Chapter 4: “Defining and Using Models”. There are (of course) two sections. The “Defining Models” section starts with an explanation of why to use an ORM. Then they describe the different types of fields, and explain primary keys (and they describe the “unique=True” argument, which is new to me). Then they go into detail on foreign keys (many-to-one relationships), many-to-many relationships (both “simple” and “complex”) and a brief explanation of composition with one-to-one relationships (but no examples). That’s followed a brief description of constraining relationships with a “limit_choices_to” argument. That’s new to me, and I don’t see a use case for it, so I’d like to see a real example (rather than their contrived example of a Book model class that will only relate to authors whose name ends in Smith). Next is a detailed explanation of (the new Django feature) model inheritance, where they explain the two different approaches: abstract base classes and multi-table inheritance. They then describe the Meta inner class with a reasonable amount of detail and conclude with admin registration. They avoid a detailed explanation of the admin options, which is in keeping with this book’s intention to be more of a tutorial than a reference.
The “Using Models” section starts with an explanation of syncdb. They’re careful to explain right away that in spite of its name, syncdb will only create database tables to match models—it doesn’t do any sort of synchronization. I don’t recall TheDjangoBook explicitly stating this so clearly, but I also didn’t learn this the hard way. I think it became clear as I read through the examples. They provide a table of the manage.py functions, which I don’t recall seeing in TheDjangoBook, and if I read about the “sql\*” functions and “loaddata” and “dumpdata” (in The DjangoBook) then I’ve forgotten.
The meat of the section is in the section on query syntax. I also don’t recall TheDjangoBook explaining so clearly what a Manager is. I’ve heard the term, but until I read it in PyWDwD I didn’t realize a Manager object is returned from a model class’s objects attribute, and its methods (all, filter, exclude and get) always return QuerySets. The explanation in the (next) “QuerySet as a building block” section is also new (to me) and quite lucid. They explain how QuerySet “…is lazy: it will only execute a database query when it absolutely has to…” and explain how this allows them to be composed into complex queries. There’s a lot of detail here, including tweaking the SQL with the QuerySet method extra. Then the chapter concludes with an explanation of how to use SQL features that Django doesn’t provide.
Chapter 5 is entitled “URLs, HTTP Mechanisms and Views”. The URLs section contains a very detailed explanation of URLconfs. Then follows the “Modeling HTTP: Requests, Responses and Middleware” section, which starts a description of request objects, within which their explanation of GET and POST is helpful. And then the section gets even meatier. Their explanation of cookies and sessions is (IIRC) not covered in TheDjangoBook. The section concludes with a brief description of response objects and middleware.
Finally the “Views / Logic” section explains that views are just Python functions, that must take an HttpRequest object and return an HttpResponse object (both of which were explained previously in the “Client/Server - HTTP” section). And then they jump right in to explaining generic views. (3) Unfortunately they don’t (yet?) provide any examples, so I imagine their descriptions of the most common generic views will go over the head of Django newbies. They state that the most common use of “semi-generic” views (calling a generic view from a custom view) is “…to work around an inherent limitation in the URLconf itself: you can’t perform logic with the captured URL parameters until the regular expression has been parsed.” But they only provide one short example with no explanation of what it does. Finally they very briefly explain custom views, and describe rendertoresponse() as replacing “…the two- or three-step process of creating a Context object, rendering a Template with it, and then returning an HttpResponse containing the result.”, but I don’t believe they have yet explained what a context object is and only very briefly described templates.
The final chapter in Part II (#6) is “Templates and Form Processing”, containing (of course) two sections. The “Templates” section is more of an overview of Django templates than an in-depth description. But I did find it clear and easy to follow. I didn’t learn anything new, but I already have a reasonable amount of experience using Django templates. There is plenty of detail in the “Forms” section, and more examples than many of the previous chapters. I enjoyed reading this chapter—it’s a big improvement over the limited coverage of forms in TheDjangoBook.
Part III, “Django Applications by Example” contains four chapters, each dedicated to a different example application. Chapter 7—“Photo Gallery”—presents an example application using Django’s image upload field and a custom ImageField subclass that automatically generates thumbnails. Chapter 8—“Content Management System”—defines “CMS” and describes the “Un-CMS” Flatpages App and presents a simple custom CMS. Chapter 9—“Liveblog”—walks through the creation of a blog application, including Ajax integration. The introduction to the chapter states it “goes over everything you need to know to integrate Ajax with a Django Web application without going too deep into the specifics of complex client-server interaction or animation.” (I’m particularly looking forward to reading this chapter carefully.)
Part IV—“Advanced Django Techniques and Features” contains two chapters. Chapter 11—“Advanced Django Programming”—has plenty of meat. There are sections on customizing the admin, generating RSS or Atom feeds, generating downloadable files (including examples of a vCard, CSV, and a chart using PyCha), enhancing the Django ORM with custom managers, and plenty of detail on extending the template system (by creating custom template tags, inclusion tags and custom filters) and using other template engines (Mako in this case). Their explanation of inclusion tags is detailed and walks through a useful example of how to create a template tag to display a calendar grid.
Chapter 12—“Advanced Django Development”—also has plenty of satisfying detail. There’s a section on writing utility scripts using Django, with a couple examples: one that can be run using cron to delete old records, and a script to import email from an mbox file to a database using a Django model. They provide plenty of good advice and background on caching. I’m sure it’s just a sign of how little I know about Apache, but I had never heard of “ab”, the Apache Bench tool. I applaud the authors for taking the time to describe its use at the beginning of their caching session, and using it to show measured performance improvements. A section on testing covers doctest & unittest, testing models, testing your entire web app, and testing the Django codebase itself. And there’s a couple paragraphs on customizing the Django sources, where they (rightly) discourage the reader from doing so unless it’s worth contributing the changes back to the Django project.
There are 6 appendices. Appendix A is titled “Command Line Basics”. It is a very simple introduction to using a command-line environment on Linux or Unix. They cover common commands, options and arguments, pipes and redirection, environment variables, and the PATH. I think this would be quite useful to someone with no command-line experience (perhaps with a strictly Windows background).
Appendix B covers “Installing and Running Django”. Including installing Python (and brief mentions of Easy Install and IPython), installing Django itself, choosing and configuring a web server (they cover Apache & mod_python, WSGI, and FastCGI with flup), and choosing and configuring an SQL database (they covert SQLite, PostgreSQL, and MySQL, with a quick mention of Oracle and Microsoft SQL Server and IBM DB2).
Appendix C is titled “Tools for Practical Django Development”. The first section is on version control. They discuss the fundamentals of branches and merging, describe subversion and the Mercurial and Git DVCSs, and then walk through using version control on a Django project (using Mercurial). There’s a brief section on project management software, with a description of Trac. And a brief section on text editors with descriptions of Emacs, Vim, TextMate and Eclipse.
Appendix D is a quick 3 pages on “Finding, Evaluating, and Using Django Applications”, with brief sections on where to look for applications, how to evaluate them, how to use them, and sharing your own applications.
Appendix E covers “Django on the Google App Engine”. They focus on porting an existing Django app to App Engine, and creating a new Django app written specifically for App Engine. While not exhaustive, the detail on porting looks useful. (I hope to come back to this in more detail later.) But the intention of the appendix is to give an overview; they conclude with a list of online resources for more detail.
The final appendix F (and conclusion of the book) is two pages on “Getting Involved in the Django Project”. They describe ways to contribute that don’t require any programming, ways to contribute involving code that “still don’t require Herculean effort”, and offer ideas for contributions that would “have a significant impact on the Django community”. The conclude by pointing the reader to the two Django mailing lists, IRC and some Django community web sites. It feels like an appropriate ending to the book.
In conclusion, I recommend Python Web Development with Django to anyone considering (or just starting) using Django to build a web site. I recommend it over TheDjangoBook, not just because PyWDwD is more up-to-date, but also because I think it does a better job at explaining all the new concepts required when using a web framework. My main concern when reading the rough cut version was that there were not enough examples. But that’s been almost entirely rectified in the published book. (And the book should empower the reader to go out an find more open source examples as needed.)
The only other thing I noticed that was missing was examples of writing Django applications (Django terminology for modules built to be reusable, if possible). But a book can’t be everything to everyone, and that’s a niche that James Bennett’s book Practical Django Projects looks like it will fill nicely. (I hope to review it eventually.)
One other Django book I hope to find time to read is Marty Alchin’s Pro Django. It looks like it will pick up where these other two leave off.
Footnotes:(1) I made note of the following tidbits along the way:
- I didn’t know about the enumerate() built-in function. I’m sure there have been times where I could have used that to simplify my code. They have an explanation of a handy way to use enumerate in Django models that you’ll also find used in this Paul Bissex blog post.
- I also wasn’t aware of the sorted() built-in function, which would also simplify my code at times in place of the list sort() method (which doesn’t have a return value).
- Their explanation of “tuple-related gotchas” will be quite helpful to Python newbies.
- I wasn’t aware of “from . import X” and “from .. import Y”. I can think of one specific place in my code where “from ..” will help.
- Their entire “Common Gotchas” section is excellent reading.