Thoughts on Django After My First Project
Posted by Michael Shepanski, on October 14, 2009

So I finally bit the bullet and made a blog.  This started as more of an effort for me to learn Django.  However, I quickly realized I wanted a place to post about all the things I am learning along the way.  So this place will tend to be about coding Python, Django, jQuery, and the occasional personal post.

What better for a first post than talk about my experience writing my first Django app, so here it goes in my finest form.  I don't claim to be a Django wiz, these are just the thoughts I currently have after reading all the documentation, taking it in to the best of my abilities and applying it to make this website.  Take the below comments with a grain of salt.

The Admin Interface is Pretty Awesome

The easiest and most obvious advantage of using Django is the auto-built administrative panels. I have never before liked automated admin anything, because I am *big* into customization.  If the admin UI doesn't match the design of the site, I am not happy with it.  "What good is an admin panel without the animated spinning flame gifs I use throughout the main site?"

Giving this some more thought, what does it matter?  The only people to see the admin panel are the people who own it.  This is more of a personal issue than anything wrong with Django.  And after using the admin panel for a few weeks, I have to say I am pretty impressed, even if it is quite a bit of work to make it perfect, it is still a lot less work than writing it myself.  I'll admit though, I did pimp out Django's admin interface with Grappelli's modifications, and I have to say I love every bit of it.

Django's Template Language Taught me to use Templates Correctly

I think I always used template languages incorrectly.  Starting from the days of PHP, mixing back-end scripting code with HTML seemed like a great idea, and at the time it was.  Over the years every single project I worked on became overwhelmingly hard to maintain.  I quickly realized I needed to organize myself better and this is where Python comes in.

I made my own poor man's framework written in Python, using Cheetah for a Template language and hit the town.  I could now sort of separate my model from my view.  I say sort of because I never implemented all the various functions to format the data such as Django's filters.  I always did my string manipulation within the view itself using #set and creating new variables.  The problem with this is that your template now has a bunch of unnecessary logic in it just for formatting.  It's all too easy to fall into this pattern when using PHP.  But sometimes, being able to do this makes sense as shown below.

While Django's template language is good, I do still see myself desiring more. I'll write more about each of these later, and possibly have solutions for them by then, but as a noobie to Django, this is what I miss.

  • I wish it was easier to use if statements.  Why don't we have greater than, less than, why do I have to use {% ifequal ... ...%} instead if the more obvious {% if ... == ... %}?
  • I want to be able to call another template and pass it parameters.  Suppose I have a reusable widget, a Side Pane that I use many time in my page layout.  In this side pane I only ever change the title and contents but all the surrounding HTML/CSS stays the same.  It would be great to do something like the following (one of the very few things I think JSP does right):
      <include sidePane>
        <param title>Hello World</param>
        <param content>It's Sunny Today</param>
      </include>
  • I want to change the class of an element based on something from the application.  Take example below which I find very messy:
      <div class="blog_comment {% ifequal comment.email blog.post.author %}author_comment{% endifequal %}">...</div>
    I think the following might be much cleaner, allowing me to more clearly separate my div definition from my logic around the classes needed.
      {% set comment_type = 'author_comment' if comment.email == blog.post.author else 'user_comment' %}
      <div class="blog_comment {% comment_type %}">...</div>

There's an App For Everything!!

Everything is a Django app, and there seems to be an app for everything.  This is great on the surface, then confusing, followed by maintainability hell if used wrong ..and all I wrote so far was this crazy simple website.

I wanted to make a blog.  So I started a new Django application.  Everything was going fine, an I liked the idea of apps.  Then I needed a comment system.  Great, Django comes with one.  However, I didn't want to implement it exactly how the author of the contrib/comments application did.  For one, I wanted to submit my comments via Ajax for a better experience.  This is where is got confusing.  I was no longer writing a simple app, but trying to mangle my edits into the currently exiting comments app to both save time and follow the DRY principals.  In the end it worked out with a little nudge from Brandon Konkle's post about DRY Ajax Comments.  Almost there, I still wanted to add avatars for the people that posted comments, another app!

In the end I have 4 applications, just to get a simple blog with comments up and running.

  • The main blog application.
  • Django's contrib/comments.
  • My own extension to Django's comments, adding AJAX via generators.
  • A generic gravitar app to get avatars.

I like the DRY principals and all, but code gets of of hand very quickly with hard to follow generators all over the place.  What seems like maintainability on the surface is just a confusing mess of hacked together pieces of code from all over the place underneath, and this is how the community says it should be done.  What I would like to have done is just have two applications, A blog, and a comment system.  Maintainability would be much more simpler for myself, and I wouldn't have all these sources to keep checking for updates.  ..Maybe I am trying to be too extensible.

There is No Quick Reference

The documentation for Django is good, but not amazing.  Everyone raves about how good it is, I feel I will be shunned for not liking it.  Everything is an article, for the beginner.  This is great when your reading it for the very first time.  However, after that first time, I always need to go back and quickly look something up for reference or example.  This is not easily done with when everything is a full length article.

Two documentation pages I currently love, PHP and jQuery.  Each function has it own page, if I know the function name I want to read up on, I can type it into Google, read the first sentence or two, get the information I need and move on with my life.  Try doing this this Django, and you find yourself needing to spend a good 5 to 10 minutes to get the context then relate this to your current needs.

File Structure from a High Level is a Mystery

This one may be my own fault.  As a newcomer the Django and after reading all the documentation over the course of several weeks I still have yet to find where this is discussed, or maybe it's not there.  Everyone I talked to about how to start my first project, how to integrate it with wsgi seems to do it slightly differently.

  • Where does the media directory go in relation to my django project?
  • Should my Django project be named after my website?
  • Should I put the Django Project inside a directory already put aside for my website?

At first I ended up with the weird structure /home/mike/pushingkarma.com/pushingkarma/... The first pushingkarma is the directory set aside for everything related to my site.  The second one is the Django project.

The double name here bothered me, so I made one directory 'pushingkarma.com' that was my django project as well as everything related to my site all dumped in one directory.  It's working for me, but its not recommended from people in the IRC channel for security reasons I have yet to understand.  It would be nice to see a high level file structure section added to the Django Documentation.

The Django Community is Amazing and Friendly

This is something I have never seen in my past while developing web applications.  A community that cares, and cares a lot about philosophy and teaching new people not only the 'accepted way' of solving a problem, but also why they decided this is the best way to solve it.  This is one of the major reasons I really think Django and I will have a long relationship together.

Conclusion

I love Django, and I am here to stay.  The comments above are all random items I was slightly bothered by while getting started.  As time passes I am sure many of these gripes will be solved or someone will yell at me saying I am doing it wrong.  I am open to either case, but please be constructive, I am new after all.  I look forward to becoming part of this community and helping Django get better.

8 Comments
November 11, 2009 at 02:11 a.m.

Try Jinja for templating. It's quite easy to upgrade a Django template to be compatible with Jinja, and Jinja feels much more robust. It includes both code macros to build reusable templates and has if statements that make sense!

Emily
November 11, 2009 at 03:11 a.m.

Have you played with context processors at all? I use them for the Side Pane template variable issue. Obviously I set the values in the views, not in the template doing the including though, but they are useful.

Also, I don't know if this is the wrong thing to do, but when I find that I want to do something like:

...
I would find myself either writing a template tag or filter to return "author_comment" or an empty string depending on values passed, or adding a method like is_blog_author to the comment model (it all depends on what is more appropriate).

I think it is intentionally hard to do too much logic in the templates in django, because the logic probably ought to live elsewhere.

hmp
November 11, 2009 at 04:11 a.m.

You can pass a parameters to a template, although it's a bit awkward.

{% with 42 as param1 %}{% with 34 as param2 %} {% include "blah.html" %} {% endwith %}{% endwith %}

Jeremy Dunck
November 11, 2009 at 08:11 a.m.

"instead if the more obvious {% if ... == ... %" It's coming. See "Templates-02" here: http://code.djangoproject.com/wiki/Version1.2Features Meantime, maybe you can try this snippet, which the work will be based on? http://www.djangosnippets.org/snippets/1350/

"I want to be able to call another template and pass it parameters" I think you want this: http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags

"I want to change the class of an element based on something from the application." Yeah, I agree that's messy. A little better if you use the smart {% if %}.

I think this is what you're asking for in a "quick reference"? http://docs.djangoproject.com/en/dev/ref/ It's not entirely obvious from the main doc page, but it does exist. :-)

Jeremy Dunck
November 11, 2009 at 08:11 a.m.

Ugh, formatting fail. :-/

November 11, 2009 at 05:11 p.m.

Take a look at http://github.com/montylounge/django-sugar - it includes a replacement {% if %} tag that's more robust. Last I checked it was slated for inclusion in Django 1.2.

As far as the reusable bits of html goes - you can use {% include 'fragment.html' %} and {% with %} to set context variables since the names are hard coded in the reusable fragment...

Oh and as far as navigating the docs: I build myself a local copy (see http://eddymulyono.livejournal.com/74322.html) and build a site-specific app for it with Prism. The Table of Contents is most helpful when starting out and the module index is useful once you know what you're doing...

November 11, 2009 at 06:11 p.m.

I'm on the grappelli dev team, glad you like it :)

There is No Quick Reference

Yeah actually there is..

In your project root run "python manage.py shell"

from django.contrib.auth.models import User help(User)

November 11, 2009 at 06:11 p.m.

I'm on the grappelli dev team, glad you like it :)

There is No Quick Reference

Yeah actually there is..

In your project root run "python manage.py shell"

from django.contrib.auth.models import User help(User)

P.S.: comment preview seems broken :|

Leave a Comment

Michael Shepanski

I am a software engineer working in the Boston area. I love Python, and I love tinkering with code during my spare time.