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!

2008-10-09

Cholecalciferol

There's something I know you need and probably aren't getting enough of. It's Vitamin D, specifically Vitamin D3 also known as cholecalciferol. Personally, I take at least 5,000IU of it a day unless I've spent some quality time in the sun. I also give it to my kids in appropriate doses.

To learn about why you might want to get more Vitamin D3 in your life, I recommend starting with The Vitamin D Council's site. Their October 2008 newsletter inspired me to post this.

One thing I like about Vitamin D3 is that it's cheap, especially in the summer time when it's free (your skin makes it for you when it is exposed to sunlight)! When it isn't free, I buy it from iHerb.com whom I've used for many years with no complaints. If anyone is interested, feel free to use coupon code PEN753 for $5 off your order for first time customers. Disclaimer: If you use that coupon, I get a referral fee.

In case you were curious (and I was), the cholecalciferol in commercial supplements is probably derived from lanolin.

And here is a link to the specific brand of Vitamin D3 that I use:

While I'm mentioning it, here's the other supplement I take 400 - 500 mg of nightly:

Those magnesium people need to get their act together and form a council so I'd have something to link to. In lieu of that, here's something by Dr. Michael Eades on his favorite supplement.

2008-06-28

Sweet Somethings!

A friend of mine, Mike,  just announced the opening of  his online store: Kai's Candy Company. I love the look of their site. Their Handmade Japanese candies are unique here in the States. They are currently offering Obama and McCain candies for the 2008 political season. I really need to find out what that super secret surprise candy is too!

Mike and I worked together at Penn. When he came for his interview, he thought we were looking for a perl programmer because that was what he was told by the recruiting agency. We were actually looking for someone with python experience of which he had little to none of at the time. I'm so glad that didn't get in the way of him getting the job because it was my pleasure to work with him. I hope his new venture is a sweet success!

2008-06-24

Netflix Disappointment

Netflix recently announced that it was removing a feature from its service. It happens to be a feature that my family relies on. They say the decision is final and there's no indication that they plan to replace it. That said, we dropped two dvds from out account today and we'll drop the rest when they go through with it if not sooner. At least they made that part easy!

More reactions from users:

2008-06-11

This American $152,000

I listen to the This American Life podcast each week and the program has recently started asking for donations to cover their bandwidth costs of $152,000 a year. It seems like a waste of money when things like bittorrent and Amazon S3 exist in the world. I guess they opted for good and fast from their list of three options.

2008-05-20

I'm all up in ur top

By way of Dan Benjamin, I see this thing called Alltop. Next, I see their python area. Finally, I see that this blog, Speno's Pythonic Avocado, is listed among the top sources of python news. Clearly, this Alltop thing is not to be trusted.

Further proof is that the excellent, JUNKFOOD SCIENCE,is completely missing from their Health section.

*plonk*

2008-04-30

the machine that goes PING!

Meet ~bin/sonar.
#!/bin/sh
# usage: sonar <host or ip address>
while :
do
ping -c 1 $1 && say "PING!"
sleep 30
done
This is a super fancy network monitoring tool. The original version of this was from another friend named Mark (not he of greenbar fame) and it played a submarine style sonar "ping" sound when a ping was successful. When you're waiting for your server to come back up, and you have time for a nap until it does, a tool like this is just what you need.

This version relies on the Mac OS X /usr/bin/say command.

Eat your heart out peep.

EDIT: Yeah, as originally posted the ping command was missing an argument. I blame myself and blogger's difficult to use posting. Thanks, Aaron.

2008-04-21

Drop Anything

Sometimes you need drag and drop support for your scripts. Luckily, there's this Mac OS X tool which turns your scripts into applications onto which you can drop files and present their paths as arguments to your script. It's called DropScript and you can find it on Willfredo Sanchez's software page.

I used it to feed input to a remote python program and it works perfectly. Of course you need to give it a cute icon so that people will want to drop files on it.  Here's one I like:

DomocunCreature Icon

2008-04-18

This is getting awk-ward

Ideas from readers DrewP and Justin have greenbar approaching the size of the original awk version. Thank you both.

#!/usr/bin/python -u

import sys

try:
pat = sys.argv[1]
except IndexError:
pat = None

green = True
for line in iter(sys.stdin.readline, ""):
if (pat and pat in line) or (not pat and green):
print "\x1b[7m%s\x1b[0m" % line.rstrip()
else:
print line,
green = not green

2008-04-11

Please to dance round for the one called the Greenbar

Inspired by what I can only guess is my unsightly python version of greenbar, drewp has created a version with 100 percent more fun to look at. Thanks!

Drewp's version (see here) is what I always hoped greenbar would grow up to look like when it was written by someone who was not me. I wish the enumerate thing would work - I tried that originally too, but no, it's not to be. It works fine if the input is a regular file, but not when you want to read the stdout of another process. There's internal buffering in python that chunks up the input making the most common use of greenbar, watching a growing log file, hopeless.

Combining the two versions results in a super hybrid that works and is easy on your eyes. Tada!
#!/usr/bin/python -u

import sys

try:
pat = sys.argv[1]
except IndexError:
pat = None

lineno = 0
while 1:
line = sys.stdin.readline()
if not line:
break
if (pat and pat in line) or (not pat and lineno % 2 == 0):
print "\x1b[7m%s\x1b[0m" % line.rstrip()
else:
print line,
lineno = lineno + 1
P.s. The original awk version was shorter still. If I find a copy, I'll bury it so that python looks better.

2008-04-08

spice up your tail minus effs with greenbar

I've been missing this tool for a while now. The original "greenbar" was in written in awk, probably by my friend Mark S. It took input and inverted the text of every other line (like greenbar printer paper). It made watching log files scroll up your terminal much easier to parse.

Here's my python version which has one new feature. It can be given a string argument in which case it will only highlight lines in its input that contain that string.


#!/usr/bin/python -u

import sys

REG = "\x1b[0m"
INV = "\x1b[7m"

try:
pat = sys.argv[1]
except IndexError:
pat = None

i = 0
while 1:
line = sys.stdin.readline()
if not line:
break
if pat:
if pat in line:
print INV, line,
else:
print REG, line,
else:
if i % 2 == 0:
print INV, line,
else:
print REG, line,
i = i + 1
if i:
print REG

It's important to use unbuffered I/O, thus the "-u" flag to python is used along with sys.stdin.readline().