validate the css validate the xhtml

HackerMoJo.com


Ceci n'est pas une blog
by Glenn Franxman, Django Developer / Stunt Programmer.

Special Ops for Django

posted: 2008-02-29 00:47:20

I do a lot of hacking on django both at work and in my spare time. One of the things I like most about django is the built in admin. It's cheap, fast and reliable. But it doesn't always have the functionality you might want to add, and extending it isn't always the easiest thing to do.

So much of what I do ends up being done in an ad hoc mode. It's only after performing a task a few times that you can really begin to get to the bottom of what is common and belongs in a framework, and what isn't. So when it came time to add some features to handle blog spam last week, I guess I finally had enough context to extend django's admin in a hopefully intelligent manner.

What I've done is add what I'm calling admin actions to the standard admin mechanisms as defined in the models. The gist of it is that I've added a few new views and a single function decorator that you can use to unleash the additional functionality within the admin.

( BTW: you can get the diff to patch your instance from here. Just apply it to your django/contrib/admin folder. I'm using an older version from the .96 days. )

So once you've applied that patch, you'll have the new @admin_action decorator. It's time to play!

I've already started adding all sorts of functionality to my models. Here's an example of its use:

Suppose you've got a lot of blog spam that you want to delete. Choosing the comments individually and deleting them would be pretty tedious. We can solve this by creating a bulk deleter function in the manager class for the comments. Here's how we add multiple delete using the admin_action decorator.

In django.contrib.comments.models I add the following to the CommentManager

from django.contrib.admin.decorators import admin_action

@admin_action( name='Delete selected posts' )
def slaughter( self, id_list ):
res = ""
for id in id_list:
obj = self.get( pk=id )
res += repr( obj ) + "<" + "b" + "r" + "/>\n"
obj.delete()
return "Deleted %s" % res

When you use the admin_action decorator on a manager function it gets turned into an available action on the object listing page. You'll get check boxes next to all of the items and a dropdown control at the bottom of the list detailing the available actions. The function signature is important here. It should expect a list of integers that represent primary keys. At this point true composite keys are not supported.

Here's what you'll see:

After selecting the offending comments and choosing 'Delete selected posts' from the drop down, a quick smack on the submit button takes us to the results page where the slaughter method has been called and the results are presented.

These bulk operations are pretty useful. Especially on comments. I've added actions to ban ip addresses, re-check them against akismet, bulk approve/disapprove and send warning notices.

This type of extension is so useful, I immediately extended it to work for model methods too. When you decorate a method on model, the method shows up in a new section called 'Special Ops' just above the save/delete bar.

The method should only take 'self' as an argument in this case. Here's a lazy example for the comment model:

from django.contrib.admin.decorators import admin_action

@admin_action( name='Send a warning message to this user' )
def harass( self ):
""" Send a note to comment.email telling them to chill out. """
return "warning sent to %s" % ( self.person_name, )

You'll note it didn't actually do anything. It doesn't have to. It's just an example. One additional thing to note is that the 'name' parameter being passed in to the decorator is optional. Without it, the method name will be used.

Here's some screenshot love showing the appearance of the 'harass' action:

and the page resulting from clicking on the action:

Your actions don't have to do anything directly either. They can return instructions that link to a full external view if you'd like, or even just redirect out to an external app. For example:

from django.contrib.admin.decorators import admin_action

@admin_action( name= 'Destroy for all time after formatting the system drive' )
def burninate( self ):
return """ ********** Are you sure? Are you absolutely certain? Really? ***************
YES, I hate persistent storage

No, I'm good. l8r...
""" % self.id

@admin_action( name="Vendor tasklet" )
def outsourced( self ):
return """<scrip""" + """t>document.location = "http://example.com/task?ctnt=%s";</sc""" + """ript>""" % urlencode( self.content )

Now you can easily hook in views for spell checking, signaling your edge-caching service, advanced lookups, entity extraction, sending to a mailing list, etc.

( BTW: I know the results pages are ugly. Suggest a fix. If there's interest, I'll submit this to django proper, but I know they're working on a newforms admin anyway. If you find this useful or have questions just drop me note here. )

UPDATE: I've pulled down the latest 0.96.1 stable release, applied the patches to that and replaced the pathfile linked to above with something more people can use. To apply it to your own django, try:

$ cd django/contrib/admin
$ wget http://franxman.com/browsable/django-special-ops/specialops.diff
$ patch --strip 0 < specialops.diff

And you're off to the races, ready to add multiple delete, etc to your models.
If you'd like to receive or contrib improvements, I'm using bzr, so you can stay in sync with the whole thing by :

$ bzr branch http://bzr.franxman.com/Django-0.96.1-SpecialOps/

Am I full of shit? Tell me why. [ 298 remarks ]


A note from the author

HackerMojo.com is using a fluid layout based upon work by Dave Reeder. I'm trying to take CSS a little more seriously; but I'm having a hard time because of all of the bad syntax, browser compatibility hacks, and non-fluid layouts. If any of the other technology I used were like CSS, I'd have to set myself on fire and jump off of a cliff.

BDB and Memcached and Sedna. Oh my!

posted: 2008-02-23 05:45:09

Last week was all about NER, and OpenCalais. This week, if I'm up all night, it's because I'm mucking with the bleeding edge versions of libEvent, memcachedb, Berkeley DB and Sedna ( it feels weird to be dowloading software from a russian site on purpose ). 1024 threads seems to work fine, but I'm going to need almost 10 times that many and then as many processes to act as test clients. I ...

Leave a Comment [ 110 remarks ]

Local Sites

* denotes sites I'm associated with.

Google knows me

posted: 2008-02-15 03:32:24

I've been fighting insomnia since early december. It has come and gone for most of my adult life, but recently I noticed that google was in a position to make such diagnosis.

Read More [ 91 remarks ]

OpenCalais beats me to the punch

posted: 2008-02-11 04:57:23

I've been playing with various entity and information extraction frameworks for the past couple weeks with the goal of creating an web service for extracting the major topics from news articles. SP far, my work, such that it is, has shown promise, but is not as robust or reliable ...

Read More [ 166 remarks ]

OPA Summit 2008

posted: 2008-01-23 18:43:46

I had a great time during my limited participation at the annual OPA Summit for 2008.

This year was it was in Naples, Fl which is nice enough in itself, but the conference was held at the Ritz-Carlton Golf Resort, which was really nice and because of a booking screw-up ...

Read More [ 126 remarks ]

This blog post contains the words "V6J" and "5C6"

posted: 2008-01-10 22:45:38

I'm just testing the theory put out by F-Secure today about some of the trickery spammers are resorting to these days.

Leave a Comment [ 2098 remarks ]

Connections

posted: 2007-11-30 03:34:35

So this is the third night this week I can't get to bed before 4 AM. Out of bordeom I started googling classmates from elementary school and high school. Interesting fact of the night -- I went to high school with Yahoo's programming lead for search marketing. Small world.

Leave a Comment [ 312 remarks ]

Infographics

posted: 2007-11-30 02:10:28

If you like infographics ( and who doesn't? ) then you'll like this:

Leave a Comment [ 25 remarks ]

The Rise before the Fall

posted: 2007-11-29 00:37:07

I've seen quite a few references in the mmm...brains... link stream this past week to the new New York Times building. It's impressive. It has it's own website for chist's sake, and this video gives you a feel for what it's like to work there. But I have to wonder...

Leave a Comment [ 52 remarks ]

There are 286 entries like these. Previous Check 'em out

Copyright © 2003,2004,2005,2006,2007,2008 GFranxman. All Rights Reserved


hosting: slicehost.com. powered by: django. written in: python. controlled by: bzr. monsters by: monsterID.