2008-12-22

Missteps in Django - Part 2

My next misstep was related to using the regroup tag that I mentioned in the previous post.

First, let's take a look at the example model I'm working with.

class Shipment(models.Model):
description = models.TextField()
created = models.DateTimeField(auto_now_add=True);


I wanted to display these Shipments grouped by they day they had been created and I wanted that day formated like "2008-12-22". Since the 'created' field of the Shipment model is a datetime.datetime instance which, when viewed as a string, looks like "2008-12-23 19:16:06.700114". That was a bit too verbose and besides, I wanted shipments grouped by day, not by microsecond!

My solution was to a add a property (of course!) to my model and see if I could use that in the regroup tag. Here's what that looked like:


class Shipment(models.Model):
description = models.TextField()
created = models.DateTimeField(auto_now_add=True);

def _get_ship_date(self):
return self.created.date()

ship_date = property(_get_ship_date)

Then in my regroup tag, I could do this:

<ul>
{% regroup shipments by ship_date as shipments_by_date %}
{% for ship_date in shipments_by_date %}
<li>Shipments for {{ ship_date.grouper }} </li>
<ol>
{% for shipment in ship_date.list %}
<li> {{ shipment.description }} </li>
{% endfor %}
</ol>
{% endfor %}
</ul>


Hey, that worked, but this was another of my newbie missteps because there was an aspect to the regroup tag that I had overlooked (this series should be called RTFM maybe?). You can apply a filter to the attribute you are regrouping on like so:


{% regroup ship_list by created|date:"Y-n-d" as shipments_by_date %}

And you're done.

2008-12-17

Missteps in Django - Part 1

Welcome back fellow Avocadoists! I finally got something up and running in Django and I'm going to tell you about some problems I had learning and using Django in the process. I'm working on my own as the programmer and the designer so I'm sure that colors my view of things.

My first issue was with in Django's templates. Namely, there seems to be no way to look things up dynamically in a dictionary based on the value of another template tag. I'm not even sure that makes sense so here's an example of what I was trying to do:
# the python part in your view method
things_by_day = {
'2008-11-28' : [thing1, thing2],
'2008-11-29' : [thing3, thing4, thing 5],
'2008-11-30' : [thing6],
}
days = d.keys()
days.sort()

# The Django template part
{% for day in days %}
Here are the things for {{ day }}
{% for thing in things_by_day.day %}
do the thing with the list of things
{% endfor %}
{% endfor %}

So the part in the template where it says "for thing in things_by_day.day" is the part that doesn't work the way my brain expected it to. I expected the value of "things_by_date.day" to be the Python equivalent of "things_by_day[day]" but instead Django's template language translates this as "things_by_day['day']". It treats the string "day" as the key. Fail.

I figured out there was a way to do almost what I wanted using Django's regroup tag, but "No sir! I don't like it!"

Here's what the template part looks like using regroup. Note that in the following template "things" is a queryset on a model with a field named "created" instead of a simple dict or list.


{% regroup things by created as things_by_date %}
{% for thing_date in things_by_date %}
Here are the things for {{ thing_date.grouper }}
{% for thing in thing_date.list %}
do the thing with the list of things
{% endfor %}
{% endfor %}


I find this syntax noxious and I can't remember what name to use where. In the process of writing this, I got it wrong in nearly every possible way. It's probably still wrong (I'm sure you'll let me know). What's with the magic names like "grouper" and "list"? I really just want to let Python be Python and use a dictionary in a normal way. I understand the limitations of Django's template system and why they were made and for the most part I support those decisions. Then the ice weasels come.

I'm sure someone has made a new template tag to do dict lookups the way I was trying to do. It may be this one. Please feel free to let me know in the comments. I'm still quite new to Django and eager to learn more. Thanks!