Archive for February, 2007

Code Search Engine – Krugle

Bad name but a great service for programmers.

http://www.krugle.com/

Comments off

Malcolm Gladwell

http://www.ted.com/tedtalks/tedtalksplayer.cfm?key=m_gladwell

Malcolm talks about how there is no perfect Pepsi but rather only perfect Pepsis. He describes how it is important to understand humans have variability. Some great anecdotes. Check out the rest of the site while you’re there.

Comments off

Work life update

Here’s a few cool projects that I’ve worked on over the past couple years. Enjoy.

http://www.nothingbutnets.net
(I did a bunch of the set up on this site. The design was created by a company in Vancouver)

http://naturalareas.saleient.com/
This site is a survey for the city of Edmonton to see what the citizens think of the local natural areas. This was very successful and could lead to some more work with the city in the future. I worked with Mike Evans (http://www.teleologic.ca/) and James Mireau (http://www.taskone.com/) on this. Mike did all the communications work and James put together the design. I created the survey and did the statistical analysis. The survey is just one part of the project.

http://www.allaboutelectrical.com/
This site is just starting out but it’s going to be cool. Ask questions about electrical matters.

http://www.mbveneer.com/
I built all the back end systems. The design was done by a company in Calgary. In particular, check out http://www.mbveneer.com/designzone-covermyworld.cfm and try building a project.

http://www.albertasoccer.com/
I’m currently working on trying to get them to update the site. It could look so much better.

The land developer’s project management software is at http://www.aceraprojects.com/ and it’s for Acera (www.acera.ca). There’s a demo available at http://pm.pivotib.com/ but it really needs a bit of an introduction before you can wade into it.

Of course there’s also my other sites like www.saleient.com and www.conflux.ca

Now, if you’re interested in seeing the cools stuff that’s emerging on the internet you could visit these sites:
http://www.techcrunch.com/
http://digg.com/

A couple blogs that I check frequently:
http://blog.guykawasaki.com/
http://headrush.typepad.com/creating_passionate_users/
http://www.goodexperience.com/index.php
http://www.37signals.com/svn/

Some of my friends are doing cool things too:
http://www.markwells.ca/ – Mark writes on Alberta Politics and other miscellaneous topics.
http://www.1024media.com/ – My friend Branden is an expert at getting web traffic to his clients’ sites.
http://www.liftinteractive.com/ – These guys are upstairs in my building. They’re releasing a new product, http://getparade.com/, very soon.
http://inviteright.com/ – These guys are also in the building. Online event planning.
http://www.fissionmediagroup.com/ – These guys are in the building as well. I’m working on a upcoming project with them.

Comments off

Django Newforms

Binding a form to a model instanceDjango’s newforms module provides the helper method ‘form_for_instance’. The method will return a Form similar to the one returned by form_for_model but the initial data will be populated by the instance’s data. The form will have a ‘save’ method which will save changes to the instance to the database (unless it is passed the commit=False argument) and will return the instance itself.

Sometimes, however, it is desirable to use fields different from the default. In order to bind a form to an instance one will have to provide __init__ and save methods.

The __init__ method should be defined as follows:


def __init__(self, data=None, auto_id='id_%s', prefix=None,
initial=None, instance=None):
  if instance is not None:
    self.instance = instance
    new_data = {}
    # Populate new_data using 'instance'
    # ...
    data = new_data
  else:
    self.instance = None
super(MyForm, self).__init__(data, auto_id, prefix, initial)

The __init__ method will save the original instance in self.instance and pass the data it contains to the superclass (most likely forms.Form). The bound form will be created with MyForm(instance=MyInstance). To use the form for creating new instances it can be created with MyForm(request.POST).

The save method will look similar to the following:
def save(self, commit=True):
  if self.instance is not None:
    instance = self.instance
  else:
    instance = InstanceModel()

# Construct the instance below using self.clean_data
# Using self.clean_data ensures everything is validated.
# ...

if commit:
  instance.save()
return instance

It should be noted that one will not be able to save ManyToMany data without saving the instance first. If the model contains M2M fields then commit=False will not make any sense.

Views

Your add+edit view should look something like the following:

def add_edit_model(request, id=None):
if id is not None:
instance = MyModel.objects.get(id=id)
InstanceForm = MyForm(instance=instance)
else:
InstanceForm = MyForm()

if request.POST:
form = InstanceForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(‘/whatever/url/’)

return render_to_response(‘template.html’, {‘form’: InstanceForm})

Comments off

Django Quickies

Debugging in templates

<pre>{% debug %}</pre>

<pre>errors
{{ form.error_dict|pprint }}</pre>

<pre>data
{{ form.data|pprint }}</pre>

Example of Edit Inline

models.py

class Poll(models.Model):
    question = models.CharField(maxlength = 200)

class Choice(models.Model):
    poll = models.ForeignKey(Poll, edit_inline=models.STACKED, num_in_admin=3)
    choice = models.CharField(maxlength = 200, core = True)
    votes = models.IntegerField(core = True)

urls.py

urlpatterns = patterns('',
    [...]
    (r'^poll_update/(?P<object_id>d+)/$', 'django.views.generic.create_update.update_object', {'model': Poll})
)

templates/myapp/pollform.html

{% extends "base.html" %}
{% block content %}

<pre>errors
{{ form.error_dict|pprint }}</pre>
<pre>data
{{ form.data|pprint }}</pre>

<p>Today's question is: <em>{{ object.question }}</em></p>

<form method="POST" action="./">

     <label for="id_question">Question:</label>{{ form.question }}

       {% for the_choice in form.choice %}
        {{ the_choice.id }}

        <TABLE>
        <TH><label for="id_choice.{{ forloop.counter0 }}.choice">Choice
        <TD>{{ the_choice.choice }}
        <TH><label for="id_votes.{{ forloop.counter0 }}.votes">Votes
        <TD>{{ the_choice.votes }}
        </TABLE>
   {% endfor %}

    <input type="submit" />
</form>

{% endblock %}

Send Emails

views.py

from django.core.mail import send_mail

send_mail('Subject here', 'Here is the message.', 'from@domain.com',
    ['to@domain.com'], fail_silently=False)

settings.py

EMAIL_HOST = 'domain.com'
EMAIL_PORT = '25'
EMAIL_HOST_USER = 'username'
EMAIL_HOST_PASSWORD = 'xxxxxxxx'

Generate RSS

from django.conf import settings
from django.utils import feedgenerator
from nm.models import Newsitem
import os

def generate_rss(self):

    file_name = "latest_news.rss"
    file_path = os.sep.join([settings.MEDIA_ROOT, file_name])
    file_url = os.sep.join([settings.MEDIA_URL, "site_media", file_name])

    feed = feedgenerator.Rss201rev2Feed(
        title=u"Newsmemory",
        link=file_url,
        description=u"Dernières nouvelles",
        language=u"fr",
    )

    qs = Newsitem.objects.select_related().filter(...)[:50]

    for r in qs:
        text = "<br />".join([r.source.name, "%s" % r.time, r.text])
        feed.add_item(title=r.title, link=r.get_absolute_url(), description="")

    fp = open(file_path, 'w')
    feed.write(fp, 'utf-8')
    fp.close()

Reuse Login / Logout

settings.py

INSTALLED_APPS = (
    'django.contrib.auth',
    [...]
)

urls.py

 (r'^accounts/login/$', 'django.contrib.auth.views.login'),
 (r'^accounts/logout/$', 'django.contrib.auth.views.logout'),

app_name/urls.py

(r'^accounts/profile/$', 'projectname.invoice.views.index'), # default page after login

templates/appname/registration/loggedout.html

templates/app_name/registration/loggin.html

{% block content %}

<div id="box"><h4>Login</h4></div>

{% if form.has_errors %}
<div id="alert">
    <p>Your username and password didn't match. Please try again.</p>
</div>
{% endif %}

{% if user.is_authenticated %}
<div id="alert">
    <p>You are already logged in as "{{ user }}".</p>
</div>
{% endif %}

<form method="post" action=".">
<P>
<table>
<tr><td><label for="id_username">Username:</label></td><td>{{ form.username }}</td></tr>
<tr><td><label for="id_password">Password:</label></td><td>{{ form.password }}</td></tr>
</table>
</P>
<p>
<input type="submit" value="Login" />
<input type="hidden" name="next" value="{{ next }}" />
</p>
</form>

{% endblock %}

Creating and Using Custom Filters

projectname/invoice/templatetags/

__init__.py
custom_filters.py

projectname/invoice/templatetags/custom_filters.py

from django import template
from django.conf import settings

def nop(value):
    return value[3:-4]

register = template.Library()
register.filter('nop', nop)

projectname/settings.py

INSTALLED_APPS = (
    'projectname.invoice'
)

projectname/templates/invoice/customer_detail.html

{% load custom_filters %}
{{ object.address|linebreaks|nop }}

Reuse Django Admin Widgets and Graphics

urls.py

urlpatterns = patterns('',
    [...]
     (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', {'packages': 'django.conf'}),
)

settings.py

ADMIN_MEDIA_PREFIX = '/media/'

template file

<script type="text/javascript" src="/jsi18n/"></script>
<script type="text/javascript" src="/media/js/core.js"></script>
<script type="text/javascript" src="/media/js/admin/RelatedObjectLookups.js"></script>
<script type="text/javascript" src="/media/js/calendar.js"></script>
<script type="text/javascript" src="/media/js/admin/DateTimeShortcuts.js"></script>

<img src="/media/img/admin/icon_changelink.gif">

Comments off