Blogged: Scrum and Bugzilla

I blogged! But this time it was at the Mozilla Webdev blog. It’s all about this little thing I made called Scrumbu.gs. Go check it out. Do it now.

Scrum and Bugzilla

PassThroughManager for Django

Update 3/30/2011: This has been merged into Django-model-utils (Thanks to Carl Meyer). There is a ton of useful stuff in that package. You should really be using it. I am.

Django’s built-in Model Manager and QuerySet classes include plenty of useful methods. But often you’ll want more. Django makes it very easy to subclass these built-ins to add your own properties and methods. However, more often than not, you’ll want the same methods to exist on your new manager and queryset. This is also easy, but requires a lot of boilerplate code to accomplish.

I found a project that helps with this. Django-model-utils includes a number of helpful methods and classes for most Django projects. I tried using the manager_from method from this project to solve the problem I mentioned above. It worked for the simple cases, but my tests started failing for a more complex one. It turns out that the method employed in manager_from causes problems when pickling the resulting querysets. Django querysets are designed to be picklable, so this was troubling. It seems to stem from the fact that the actual queryset classes produced by this method are dynamic, and thus don’t exist in any importable way. The pickle and unpickle methods need to be able to import the queryset class however.

To solve this problem I wrote a class called PassThroughManager. If you have a simple set of methods you want to exist on a manager and queryset, you can do the following:

class PostQuerySet(QuerySet):
    def enabled(self):
        return self.filter(disabled=False)

class Post(models.Model):
    objects = PassThroughManager(PostQuerySet)

You’d then be able to use both Post.objects.enabled() and Post.objects.filter(other=’stuff’).enabled(). If you had other methods you wanted to add to your manager but not your queryset, just subclass PassThroughManager and you can do anything you want. This method has the advantage of maintaining picklability, and is a bit more readable in my opinion. Grab the code and try it for yourself in the Gist below. Feedback is most welcome and encouraged.

Cookies for Django

Until yesterday I thought the new messages framework in Django 1.2 was doing things stupidly. I like the Fallback backend; it uses signed cookies to store the messages that will be displayed to the user. This avoids the DB or cache hits that’d you’d normally get from the old system, as well as those you’d get from using the session for message storage. The Fallback goes further and will use the session if your message is too big for a cookie. Awesome right? My problem was that the messages weren’t showing up on the page until the request AFTER the one in which I set the message. I could see nothing I’d done wrong at the time, so I assumed that it was just the way it worked w/ cookies, b/c cookies have to be set in the browser and are only sent back to the server on subsequent requests.

It turns out that this is, of course, not the way the messages framework was designed. It will display the messages in the current request, but only if you haven’t already called the view, thus rendering the template(s). How could it display the messages if you’ve rendered the page before adding the messages??!?!!?!?! I was being an idiot. I was trying to set messages in a view decorator, and was doing it after calling the view. That stupid bug took me a LONG time to find. In my defense however, I did have a good reason for having to call the view in my decorator before adding my messages: I needed to set cookies.

In Django, the only way to set your own cookies to be stored on your user’s browser is to use the set_cookie method on the HttpResponse class. This means that you’ll need access to the response instance before you can set cookies. To get the response in a decorator you have to call the view. Do you see my predicament?

I thought I’d found the answer in a post from David Cramer. He created a Django middleware that would allow you to set cookies using the request object. This, I thought, was perfect and would solve my problem completely. I installed his django-cookies app, changed my decorator around to use it, and ran the test suite: FAIL. David’s code has apparently not been updated in some time, and is not compatible with Django 1.2. So I was left with nothing but the idea that this was a solvable problem. I decided to write my own middleware.

My cookie middleware works pretty much the same as David’s, but with a different API. I decided to add methods to the request object itself that exactly mirror the ones on response. Check out the code, let me know what you think, and feel free to use it however you like. I plan to package it up as a Django app soon, but I wanted to get it out there in case someone else was having similar troubles.

Slicehost Dynamic DNS

One of the best things about Slicehost is their DNS service. They allow you to host and easily maintain any number of zones you want, even ones that aren’t hosted on a slice. They also provide an excellent RESTful API for automatically modifying these zones and records. This came to mind recently when my free Dynamic DNS host (EveryDNS) was sold to Dyn, Inc.. I decided it was time to grow up and move my dynamic DNS needs to a service for which I was paying. I looked into Dyn’s offerings, but their Custom DNS service is only for a single domain, and seems pricey for what you get. I know a lot of that has to do with their global distribution and uptime guarantees, but I don’t need that stuff.

So, I began writing a little Python CGI that could act as something my home router could use as a Dynamic DNS endpoint. I use Tomato on my Buffalo WHR-HP-G54, and it supports using a custom URL for this purpose. It was surprisingly easy to get this working. I have no idea if anyone else has a similar setup, uses Slicehost, and needs Dynamic DNS, but if you’re out there, I’ve released the code for my little project on Bitbucket. It’s called, not surprisingly, slicehost-dynamic-dns. Grab it, clone it, fork it, use it, whatever you want. It’s BSD licensed for your pleasure. Please drop me a line if you use it, and if you need a feature or find a bug, throw a ticket in the tracker on the Bitbucket project. You could also fork it, fix it, and send a pull request. That’d be cool too :)

Release: Django Celery Email

I just released my first Django reusable app. django-celery-email is an email backend for Django 1.2+ that uses the amazing Celery to process sending the emails out-of-band. If you’re a Python developer and have ever wanted to use a queue to send information to separate processes that will in turn do your bidding and give back to you what you need, then Celery is probably what you want, plus more amazing features that you haven’t thought of yet, but that you desperately need. We use Celery at work, and it’s been invaluable. If you need it, or are already using it, you might as well move the processing of the email your app sends to a queue as well.

The project is open source (BSD licensed) and can be acquired from PyPI via the link above. It’s being developed at my BitBucket account, so please stop by, check it out, and file a ticket if you find anything lacking or incorrect.