Python Dictionaries In Django Templates

Selecting a value using a variable key in Django is not straightforward.

For instance, today I was counting active contacts on a User model, which are referenced by a foreign key. So I’ve got


{% User.contact_set.count %}

But I realized I was counting all contacts, when I really want to do .filter(active=True)

Since you can’t (and really don’t want to) run a filter in the template, you have two options:
1) Prepare the counts in the view, or
2) Write a method in your model to count for you

Method One

I chose solution one, and used a dictionary comprehension:

users = User.objects.all()
active_contacts = {user:Contact.objects.filter(owner=user, active=True).count() for user in users}

But in the template, now we’ve got a variable key. You can’t use a variable key in dot notation in the template. This won’t work:

{% for user in users %}
{{ active_contacts.user }}
{% endfor %}

That tries to do active_contacts["user"] instead of active_contacts[user], and so you get no value returned.

Instead, I had to do:
{% for user in users %}
{% for key, value in active_contacts.items %}
{% if key == user %}
{{ value}}
{% endif %}
{% endfor %}
{% endfor %}

Method Two

The alternative, as it turns out, is probably nicer. I don’t like polluting my models with methods that are very specific to one place, but it would make my template code a lot cleaner. It would be something like this:


class User(models.Model):
#...
def active_contacts(self):
return Contact.objects.filter(owner=self, active=True).count()

And then, in the template, we could simply do

{{ user.active_contacts }}

Note, this code is untested.

So, dictionaries with dynamic keys aren’t awesome in Django, but they’re definitely workable.


General Westerly Direction

I think the way to use these big ideas is not to try to identify a precise point in the future and then ask yourself how to get from here to there, like the popular image of a visionary. You’ll be better off if you operate like Columbus and just head in a general westerly direction.

Paul Graham


2013 Resolutions

I’m not big on resolutions.

That is to say–I make tons of resolutions, and I accomplish most of them. It’s just that I don’t need the motivation of a fresh year to set a goal–I set them as soon as one comes to my brain that I decide to accomplish.

But it’s a convenient time, and all the cool kids are doing it, right?

In 2012 I had a pretty short list. I’m not sure what all was on it, however I do remember what I considered the most important: “Say No.” I did pretty well at saying no–mostly in the form of turning down request that I did not want to fulfill (“favors”), or letting people or my conscience manipulate me into doing things I did not want to do. I quit working at my own bar because it was the best thing for me. I broke an agreement I had made several years prior, that had turned into the most restrictive thing in my life. I moved back to Florida from Arkansas–intending for it to be a stop–and landed in a phenomenal job.

I also failed on some counts–middle-of-the-night rides for friends, moving furniture in my truck, and loaning money to people who haven’t paid up but have plenty to spend on themselves.

Anyhow, on with it:

 

 2013 resolutions

  • Build lots of small things I love
  • Build something that generates moderate income
  • Try to build both in one

I’m a programmer, so building things isn’t always difficult. Last year I built a script to watch the craigslist free section for new items, a daily inspirational quote site, messed around a lot with screen scraping, and started a whole slew of unfinished Django projects. I’ve spent probably the most time thinking about, researching, and coding a rough version of a video training site–like CardRunners.com, but I plan to target video games.

As usual, though, my steam has run out for most of those. I don’t craigslist much anymore, I frequently quit updating the quote site, and I still haven’t shipped a MVP for the video training site–probably because I don’t want to “run the business” for it.

I’m quite ready to build some kind of app or SaaS product that is fun, has a lot of areas to explore programatically, and is built on a profit model. I just haven’t figured out what it is yet!

For good measure, I’ll add a few more:

  • Turn off distractions
  • Buy new jeans
  • Write 500 words per day
  • Polish
  • Meet people
  • Compliment people who deserve it, strangers or otherwise

“Polish” probably could use some explaining. I want to “polish” my little projects. Instead of a craigslist script, I should have a little craigslist program with a GUI and some options, and I want my web-apps to look nice–even if that means hiring a designer.

And as for “meet people,” it goes without saying that I will meet some people, however I’d like to make a conscious, concerted effort to expand my “people” list a little.

Prediction: 2013 is going to be a year I look back on with pride. No unfathomable mistakes, less slacking, more enjoying, better people.


Pointing Dreamhost DNS to Heroku

I had a domain ( WitDaily.com ) hosted at Dreamhost that I decided to move to Heroku. (I still think Dreamhost is great, though!)

It took me a while to figure out what to do with my DNS records. Heroku has a walkthrough for Custom Domains on their service. It’s pretty straightforward, but I ran into a small hang-up trying to set my DNS over at Dreamhost: they had “non-editable” records for a ton of stuff–a bunch of subdomains, plus an A-record.

The fix? Go to “Edit” in the domain management / hosting area, and go from something like “fully hosted” to “DNS only.” At that point, all the records are editable.


June 7th

You can’t just say you’re something–you have to be the something to actually claim it. Me–I’m going to quit telling people what I am.

Happy birthday, Mom.


Rain Is Just an Excuse

Out for a run today, I could tell it was going to rain as I finished the 1.2 mile loop. My goal is to run a little farther each run than I did the run before it. On my last run I had gone about 1.6 miles.

But the rain…

And then I realized the rain was just an excuse.

And ran 2.4 miles instead. And then biked 2.4 miles. All in the rain.

There’s an excuse to quit or not do basically everything you’ll ever have an opportunity at. Just do it.


Graduation

I went to a high-school graduation today. I’ve been to several, and they all seem the same. (Bad) Attempts at inspirational speeches, self-deprecating humor about kindergarten-til-now experiences, self-back-patting.

Tonight I heard “amazing accomplishment” and “incredibly proud” so many times I want to vomit. Why are we teaching our young people that graduating high-school is something to be proud of? It’s the de-facto. It’s not even mediocre–even sub-mediocre students mostly graduate. If we expect everyone to graduate, what is there to be proud of?

They also talked a lot about the end of one “life” or phase, and the beginning of “the rest of their lives.” Mostly that will probably entail an entry into the workforce, and feeble attempts at the more widespread version of the American dream–college, a house, and a new car. Gross.

One speech stood out tonight. A bright young lady gave a nice performance, and talked about how everyone is authoring their own story–each story unique, with its own heroes and villains. I like the idea of that. I think the goal is to make your story one worth reading. Exciting, full of twists, heroes pursuing dreams and vanquishing villains.

If that’s not the plan, what is?


Accept.

I keep looking for meaning, but all I’ve found so far is that in order to be at peace with the present, we must be at peace with the past, because the present is a product of the past. Accept. Accept. Accept. Learn to love the present moment. What happened, happened. It’s difficult to understand the big picture when our lives are mere brush strokes on the canvas of reality. Trusting that it all fits together to form something beautiful is the purest form of faith. Anything else is a dangerous distraction. No contracts with God, no expectations of reward, just trust.

Paul Buchheit

And that’s where I am. I have my hopes set high, and I’m not prepared for failure. But here, now, in this moment, I have to accept the path that led me here. I’m undeniably here. I want to rise like a phoenix from these ashes, carrying my prize with me. Able to because of my new-found strength. But I’m just choking on the ashes, floundering.

But I think that the ashes in the air will subside. Things will be beautiful, because we went down this path for a reason. Unbeknownst to us, something beautiful is being painted. I can’t wait to see it, quite literally–my innards twist in ways I’ve never known, in anticipation and at the memory of their own shortcomings. But my new-found strength comes from them–my heart works in ways it never worked before. And in that terrible pain it can now feel comes its salvation–it has become what was needed all along.

I pray the ashes will subside. I want to push into the sunlight.


Project Euler – Problem 13 in Python

Problem 13 requests:

Work out the first ten digits of the sum of the following one-hundred 50-digit numbers.

Some euler problems almost look like programming exercises. There’s nothing special about this problem whatsoever, it feels like a basic file-reading exercise.

So, I stored the numbers in a file.

Opening files in python is pretty simple:

f = open('13-numbers.txt', 'r')

The ‘r’ just means “open for reading.”

Then you can loop over the lines like this:

for line in f:
    num = int(line)

In this case, the line is a 50-digit number (that python still things is a string, so we convert with int() ).

Sum up all the numbers, and then to find the first ten digits you convert back to string and use a splice:

str(total)[0:10]


Project Euler – Problem 12 in Python

Project Euler Problem 12 deals with factorization, so it’s important to get a pretty efficient function to do that. The problem reads:

The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, …

Let us list the factors of the first seven triangle numbers:

1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five divisors.

What is the value of the first triangle number to have over five hundred divisors?

So, I created a “factor” function that returns all the factors of a given number. I’ll save you the trouble of finding it later, and let you know that this is a useful function (for Euler) that should be put in your re-usable toolbelt–in my case, euler.py.

Here’s my most efficient example:

def factorize(num):
    factors = [1, num]
    for i in range(2, int(math.sqrt(num))+ 1):
        if not num % i:
            factors.append(i)
            factors.append(num / i)
    return list(set(factors))

So we fill the list with 1 and the number, and then check remainders with modulus (%) for all the other numbers up to the square root. That’s as far as we have to go, and we’ll use 36 as an example to see why:

start with [1, 36]
check 2, find [2, 18]
check 3, find [3, 12]
check 4, find [4, 9]
check 5, fail
check 6, find [6]
Done.

So even though we only went to six, we were able to get 9, 12, and 18–numbers greater than six. Any number greater than six will have a corresponding factor lower than six, so for max efficiency we don’t go any higher.

Moving on, it’s now a fairly simple matter to check each triangle number for X number of factors, in this case 500.

First, I imported my factorization function:

from euler import factors

Then I made a function to find the first (triangle) number with X number of factors:

def first_triangle_with_divisors(num):
    '''
    Find the first triangle number with
    at least num number of divisors
    '''
    count = 1
    triangle = 1
    factor_count = 0
    while factor_count < num:
        count += 1
        triangle += count
        factor_count = len(factors(triangle))
    return (triangle, factor_count)

Walking through it, we start with

count = 1

so we can determine the next number that has to be added–it allows us to make the triangle number sequence. We set
triangle = 1

…our first triangle number. And then we set up a spot for the factor_count, so that we can set up a while loop with it.

The loop will iterate until

factor_count > num

…with num being an argument the function accepts. We could hard-code this to 500, but I set it as a variable so that I can run the known case (28 is the first number with > 5 factors) to verify working code.

This code fails in one case, if you input 1 for num. It’s trivial to fix, but doesn’t matter for our application. To fix it you would just insert, at the beginning of the function:

if num == 1:
  return (1, 1)

During each loop, we increase our count, and then add it to the previous triangle number to get the new one. Then we call our factors() function on the new number, which returns a list of factors. We count them with len() and only finish if they’re over our target.

The end of my file just has a couple of cases:

print first_triangle_with_divisors(1)
print first_triangle_with_divisors(6)
print first_triangle_with_divisors(500)

And returns the correct answer.

We can speed the function for large numbers. It’s hard to be perfect, and probably harder to prove mathematically, but it makes a lot of sense that the first number with 500 divisors is probably divisible by both 2 and 3, and possibly 5 which will give it a lot of “extra” divisors.

On my machine this runs in about 10 seconds, and it’s cut fairly drastically by including an extra line:

while factor_count < num:
        count += 1
        triangle += count
        if num < 100 or num > 100 and not triangle % 2 and not triangle % 3:
            factor_count = len(factors(triangle))
    return (triangle, factor_count)

This simply means we’ll skip our most time-sinking function, factors(), if we need a high number of factors and the triangle is not evenly divisible by 2 and 3. This ONLY works if you need the FIRST number that qualifies, because you will eventually run into a number, I think, with 500+ divisors that is not evenly divisible by 2 or 3.

Of note:
Do some research on whitespace. I had an invisible error, to the naked eye, that cost me an hour of frustrating debugging–my factor function was exiting early and I couldn’t figure out why. Some weird whitespace accident with Vim, my editor of choice.