Removing Unused ContentTypes

Published on Wednesday, January 19, 2011

I've been cleaning up my personal blog a bit, and I noticed that my tagging system recently broke. I've investigated the cause, and it appears to be because I removed some apps but the contenttypes remained. This meant that whenever I tried calling a tag with a TaggedItem that had been deleted, I was getting this error:
'NoneType' object has no attribute '_meta'

The solution is to first list all app_labels for contenttypes, and then delete any not in use.
In [61]: from django.contrib.contenttypes.models import ContentType

In [62]: for ct in ContentType.objects.all(): print ct.app_label

I could then delete the unused contenttypes.
ct_list = ["delicious", "flickr", "photologue", "twitter"]

for ct_label in ct_list:
    for ct in ContentType.objects.filter(app_label=ct_label):

And no more errors! For more details take a look at David's article.

Integrate imified into Django

Published on Tuesday, January 18, 2011

I recently had the desire to send small updates to my so called lifestream page via XMPP/GTalk. I played around with Twisted Words and several other Python XMPP clients, but I didn't really want to keep a daemon running if unnecessary. It turns out imified took a lot of the pain out of it. The steps for me were as follows:
Create an account with imified, and create a URL, e.g. /app/api/
We then configure the urls.conf
urlpatterns = patterns('',   
(r'^app/api/$', bot_stream),

We then create the necessary views. So, in
from django.shortcuts import render_to_response
from django.http import HttpResponse
from lifestream.forms import *
from datetime import datetime
from time import time

def bot_stream(request):
if request.method == 'POST':
botkey = request.POST.get('botkey')
username = request.POST.get('user')
msg = request.POST.get('msg')
network = request.POST.get('network')

if username == "" or network == "debugger":
blob_obj = Blob(id=time(), body=msg, service_name="Mobile",
resp = "OK"
resp = "Wrong username %s" % username
resp = "No POST data"
return HttpResponse(resp)

To complete this little example, you can see what I used for my
class Blob(models.Model):
id = models.CharField(max_length=255, primary_key=True)
body = models.TextField(max_length = 1024, null = True, blank = True)
service_name = models.CharField(max_length=50, null=True, blank=True)
link = models.URLField(max_length=255, verify_exists=False, null=True, blank=True)
published = models.DateTimeField(null=True, blank=True)

def __unicode__(self):

class Meta:
ordering = ['-published']
verbose_name = 'Blob'
verbose_name_plural = 'Blobs'

def get_absolute_url(self):
return "/about-me/"

It maybe isn't super elegant, but it works just fine, and maybe can provide a hint if somebody else is contemplating using a homebuilt xmpp solution, or just pawning it off on IMified.

Stock Android and Postfix

Published on Sunday, January 9, 2011

I was having some issues with my personal mail server (Postfix) and my phone (Android). The logs depicted the below issue:

Jan  9 09:19:53 ip-11-222-23-223 postfix/smtpd[12345]: NOQUEUE: reject: RCPT from[]: 504 5.5.2 : Helo command rejected: need fully-qualified hostname; from= to= proto=ESMTP helo=

We can see here that the stock Android email client is doing a 'helo localhost'. One part of my file specifies this:

smtpd_helo_required = yes
smtpd_helo_restrictions =

To resolve, unfortunately, just change the order to authenticated clients are permitted earlier:

smtpd_helo_required = yes
smtpd_helo_restrictions =

You also may need to do the same for smtpd_recipient_restrictions and/or smtpd_sender_restrictions (i.e. put permit_sasl_authenticated above the reject lines).