My name is Paul Bissex, and e-scribe.com is my consulting business. I build web applications using as much open source software as possible. From September to June I teach web design and other important non-photographic professional skills to photographers. In the '90s I wrote technology commentary and reviews for magazines, newspapers, and web publications, including Wired, Salon.com, FamilyPC, the late lamented Web Review, and the Chicago Tribune. Feel free to email me.
I'm co-author of "Python Web Development with Django", an excellent guide to my favorite web framework. Its strong points include an introduction to Python, and better coverage of Django 1.0 than nearly anybody else. Published by Addison-Wesley, it is available from Amazon and your favorite technical bookstore as well.
This runs on Django, served by Apache and mod_python. The database is SQLite. The operating system is FreeBSD, on a VPS hosted at Johncompanies.com. Comment-spam protection by Akismet. Vintage topo imagery from the Maptech archive. The markup engine is Markdown.
Akismet, del.icio.us, Django, dpaste.com, Emacs, FreeBSD, Freenode, jQuery, LaunchBar, MacPorts, Markdown, Mercurial, OS X, Postfix, Python, SQLite, Subversion, TextMate, Trac, Ubuntu Linux, wmii
At least 59053 pieces of comment spam killed since January 2008, mostly via Akismet.
People are always going on about how it "only" takes twenty minutes or whatever to knock together some little application. Screencasts don't count, unless they are screencasts of somebody who hasn't done any preparation. But damn, I just built a trouble-ticket system in Django in twenty minutes. Really. Of course, I already had a running install, this is just something I added. But it was instantly useful. I assigned four tickets to myself and now I can go have dinner.
It leverages the users you already have installed to assign and attribute tickets, and uses your list of installed apps to categorize them.
This is the whole thing, a models.py file. It requires the magic-removal branch of Django.
from django.db import models
from django.contrib.auth.models import User
from YOUR_PROJECT import settings
STATUS_CODES = (
(1, 'Open'),
(2, 'Working'),
(3, 'Closed'),
)
PRIORITY_CODES = (
(1, 'Now'),
(2, 'Soon'),
(3, 'Someday'),
)
PROJECTS = list(enumerate(settings.INSTALLED_APPS))
class Ticket(models.Model):
"""Trouble tickets"""
title = models.CharField(maxlength=100)
project = models.CharField(blank=True, maxlength=100, choices=PROJECTS)
submitted_date = models.DateField(auto_now_add=True)
modified_date = models.DateField(auto_now=True)
submitter = models.ForeignKey(User, related_name="submitter")
assigned_to = models.ForeignKey(User)
description = models.TextField(blank=True)
status = models.IntegerField(default=1, choices=STATUS_CODES)
priority = models.IntegerField(default=1, choices=PRIORITY_CODES)
class Admin:
list_display = ('title', 'priority', 'status', 'submitted_date', 'submitter',
'submitted_date', 'modified_date')
search_fields = ('title', 'description',)
class Meta:
ordering = ('status', 'priority', 'submitted_date', 'title')
def __str__(self):
return self.title
This is really neat, I particularly like the idea of grabbing all the applications from the settings file - have you posted it on the django-users google group?
Cheers, Tone
Luke -- thanks for the enumerate tip, I like that, and changed the code accordingly.
Tony -- yeah, it's the leveraging of the data already in the project and the admin that makes it so satisfying. I haven't broadcast it, but this category on my blog does get picked up by the Django aggregator.
I've fixed a couple dumb usability things (e.g. not sorting by status) and posted new code above.
Ah, just seen it come through on the aggregator.
It's the sort of thing that would be a neat screencast - except what would it be....
% python manage.py startapp tracker
% python manage.py syncdb
% python manage.py runserver
(go into TextMate), paste text, save (server restarts)
(go into Safari), http://127.0.0.1:8000/admin/tracker
Have I missed anything? ;)
Cheers, Tone
Don't forget to add YOUR_PROJECT.tracker to INSTALLED_APPS in your settings.py
And the URL I got was http://127.0.0.1:8000/admin/tracker/ticket
Way cool though!
Thanks. I have to admit it's actually a bit broken due to the admin's one-column sorting restriction. I guess that just proves my point that nobody really does these things in 20 minutes!
"itÂ’s actually a bit broken"
even so could you go through it line by line and explain what's happening?
My "broken" comment was specifically related to sorting -- the admin can't sort by, e.g. priority and status.
As far a line-by-line, I unfortunately don't have time for that at the moment but I will comment on the only really interesting line:
PROJECTS = list(enumerate(settings.INSTALLED_APPS))
This generates the choice-list for the "project" field dynamically. The Python function enumerate returns a generator that produces (index, item) pairs for each item in a sequence; the list call turns that into a static list of pairs, which is what the Django model choices param wants.
The rest is fairly standard Django fare, as covered in the models API documentation.
I still use this on a couple side projects, actually. It's good for a quick "note to self". I plan on revisiting in the course of a new project this spring or summer.
Thanks for your interest!
1) How do you reply to a ticket 2) how does a user post a ticket? Via admin panel? 3) How does he/she get a response. 4) How do you limit that the user only sees his/her own ticket?
TaMeR: This is really intended for internal use, i.e. communication between staff (admin) users.
Mostly I was just taken with the fact that one could make an actually useful "application" (useful to me, anyway) with only a model.
Comments use Markdown syntax. Your comment will not appear until approved, which may take a few hours or more. Spammers will be torpedoed.
SPF-enabled spam domains
1 comment
Chess via iPod
2 comments
Aesthetics and computation
2 comments
robots.txt via Django, in one line
4 comments
zoot
Offsite, online backup: rsync.net
17 days ago
Craig
Bicycle Repair Man bundle for TextMate
25 days ago
Fazal Majid
SPF-enabled spam domains
30 days ago
Adrian Holovaty
Chess via iPod
54 days ago
Alexander Kahn
Aesthetics and computation
59 days ago
Copyright 2009
by Paul Bissex
and E-Scribe New Media
Nice work - if I hadn't already got trac set up (which python-hosting make really easy to do) I would probably have pinched this!
You can make it a little prettier by changing this:
APPLICATIONS = zip(range(len(settings.INSTALLED_APPS)), settings.INSTALLED_APPS
to this:
APPLICATIONS=list(enumerate(settings.INSTALLED_APPS))