Spooky Pony

Latest entries


New Job

August 20, 2008

I haven't written in quite a while, for which I apologize. It turns out that I'm not really a writer. By which I mean, I don't have a burning need to write, or else I'll just fall over and die. Not to knock it, that kind of compulsion is what gets things done in any given field, and I do have that compulsion in other areas, just not writing.

Which means that writing, for me, is not an end in itself, it is a means to an end.

In the meantime, I have some news! I have transferred back to the Open Systems Department here at MSKCC, where I am once again a Senior Unix Systems Administrator. I will continue working on Synapse in my spare time, while my main focus, at least initially, will be in creating web application front-ends for the FEDORA Repository project, for internal use. I will, of course, be using Django as my preferred solution. Unfortunately, I inherit an extremely complex web front-end written in Java as my pilot project. The web app, Muradora, is reasonably well-written, but my Java is, um, rusty. Happily, I'm getting back into the swing of things (no pun intended, we're using JSPs) fairly quickly. On a note of personal interest, the Fedora repository has SOAP interfaces, so I'm tasked with learning SOAP reasonably quickly. Does anyone have any pointers as to some basic tutorials, preferably in Python?

0 Comments   Full entry


Relative Paths in Django

June 22, 2008

A handy link to an article on how to set up one's Django settings.py file, to allow for relative paths:

Django and Relativity

0 Comments   Full entry


Writing Django Applications, Interim Thoughts

June 19, 2008

Some Perspective

One of the wonderful things that comes from a few days spent doing other things is a certain amount of clarity and perspective that you get when you return to whatever-it-was. In this case, I've realized that the Event model is both too complex and too cool for school. In short, I should absolutely not build iCal functionality into the Event model. Instead, what we ought to do is extract this functionality into a different Django application.

To that end, I'm going to start building django-ical. The concept is similar to James Tauber's django-atompub, where django-ical requires you to define certain methods that allow it to provide the necessary data to build ICS files. Those methods will extract the data from whatever model you choose to provide to it. The ICS files will then be available for download from the site in which they are embedded.

My goal is to build a working CalDAV application for Django. Ambitious, yes, but... truth told, I've had a bug for years about the paucity of complete groupware stacks that are easy to use. A single CalDAV server implementation isn't really the groupware stack I've been dreaming of, but it might be a step in the right direction.

The point, though, for the django-meeting application, is that Event need not define any iCal related functionality. Instead, I need to make sure the necessary data exist for each Event, which means the proper field definitions. Then, write the necessary views and wire that up to django-ical. And, errrrr, actually write django-ical...

Again, more to come later.

This post is a continuation of my earlier entry on writing Django applications.

0 Comments   Full entry


Comments Working

June 09, 2008

I am pleased as punch to announce that I have successfully added comments to this fine weblog. Which means that the standard of discourse on the web can now be lowered fractionally, yet again.

0 Comments   Full entry


Movie Review: Kung Fu Panda

June 09, 2008

My wife and I, and our good friend Bryant Frazer, proprietor of Deep Focus saw Kung Fu Panda last night. The movie was fun and I enjoyed it, but it lacked a certain something.

For one thing, Po the Panda, Jack Black's title character, performed no kung fu until, oh, about an hour into the film. In addition, when one of the kung fu masters did perform, the animators chose to make the moves so fast you can't actually see them, unless you happen to be a five year old hopped on Ritalin and sugar.

Finally, there was a distinct lack of local color and flavor to the movie. I got hints of flavor, primarily from wonderful performances by James Hong as Po's adoptive father, Mr. Ping, and Randall Duk Kim as Master Oogway, but mostly I was smacked in the face non-stop with Jack Black. And while Jack is a fine comedian, I'm not sure he really has the ability to carry a movie on his own. I'm consistently disappointed by Jack, every movie of his I see I feel it almost hits the mark, but not quite. There's really not quite enough substance to his performances.

0 Comments   Full entry


Writing Django Applications, Part 1

June 01, 2008

Introduction

I can't really claim to have huge amounts of experience with Django, seeing that I have written all of two applications using the framework. However, as I work on a third application, I see a certain process emerging out of the work I've been doing. The process is by no means formal, nor is it necessarily even correct, but in light of some discussion on the django-nyc group, I think that explaining how I go about developing a Django application may prove to be of some use to beginners. What follows is very stream-of-consciousness, in the hopes that others may learn something from following the thought process.

Step 0: Create the Basic Project Infrastructure

The very first step is to set up your basic infrastructure. Install a database engine, create a database and means of access, run django-admin.py startproject and django-admin.py startapp to set up your directory structure. Get your directory structure under version control, and possibly set up whatever other project hosting you may need or want. Google Code makes this last step particularly easy.

Step 1: Define Your Models

Here's where things really get rolling. The first thing to do is to start thinking about what your application will be manipulating, your domain objects. For our example, one application the Django-NYC group is considering building is a meeting organizer, similar to meetup.com or upcoming.org. In this example, the domain objects are going to be such things as Event, Location, Organizer, and Attendee. At a high level, these are the objects that our meeting organizer app will handle. So how does this translate into code? Well, we make a first pass at models.py, which winds up looking like this:

from django.db import models

# Create your models here.

class Event(models.Model):
    pass

class Location(models.Model):
    pass

class Organizer(models.Model):
    pass

class Attendee(models.Model):
    pass

So far, there's really not a whole lot there. But that's okay, since this process is iterative, and this is only our first pass. While we're on our first pass, though, we might want to think for a moment about Organizer and Attendee. Both of these models are going to be, basically, Users, so we probably want to set up these two models a bit differently. The canonical way to add information to the built-in User model is to create a single profile model that encapsulates the additional fields and methods for the entire site. In your settings module, you then point to that profile model and set it as your site-wide user profile. So, our initial idea to have separate Organizer and Attendee models isn't going to work, if we want them both to be able to log in and use the application. Instead, we'll need to combine the models, and differentiate them elsewhere. Since I haven't even started to differentiate them, now is definitely a good time to combine these models. For our next pass, we delete the Organizer and Attendee classes, and replace them with the following:

class MeetingProfile(models.Model):
    pass

Our iterations are small, so our improvements are not going to be too large in any given pass.

Step 2: Refine Your Models

Let's look at Location first, as it is arguably the easiest to think about (barring i18n issues). A Location has a name, and that name will provide a slug field. Locations have from one to three address lines, a city field, a state field, and a zip/postal code. They may have a room number, or a floor -- some refinement on the address that is usually held in the second or third address line. At this point, I don't think we need to get more specific than that. Locations also should have a description field, for whatever random notes need to appear.

Since Locations are naturally given to mapping, we will want some means of storing information that allows us to connect our meetings app to an online map provider. Given that I am Google's bitch, I naturally lean towards Google Maps, but since I don't know anything about geolocation, or that spiffy new standard Google came up with recently for specifying location coordinates, I'm going to punt on this feature for the moment. At some point later, I'll come back to it. I need to do my homework on it first, though, so we'll save it for another iteration.

Locations can be used for more than one Event, but there's some complexity there that needs some thought we haven't given it yet. So we'll come back to this part, too. Just to give a quick hint, though, a given Location can often host multiple Events, and a given Event can be held at multiple Locations, given some teleconferencing. This implies a ManyToMany relationship. A given Event can be held at multiple Locations also, if the Event recurs. Likewise, if a Location is not specified precisely enough, then that Location can potentially host multiple Events at the same time. Hmmm, this line of thinking may wind up in an additional model -- something like Resource, which is a generalization of e.g. a conference room, a projector, a table, chairs, snacks, etc. And a given Resource can be required or optional.

So much for a quick hint.

Locations also have one or more hosts, where a host is someone who is responsible for the Location. That person may or may not attend, and may or may not be an Event organizer, so these are some complexities we'll want to keep in mind for later. In the meantime, we have the following Location class (N.B.: I have deliberately not set the field details yet):

class Location(models.Model):
    name = models.CharField()
    slug = models.SlugField()
    description = models.TextField()

    address1 = models.CharField()
    address2 = models.CharField()
    address3 = models.CharField()
    city = models.CharField()
    state = models.CharField()
    zipcode = models.CharField()

    # punted for now
    # coordinates = models.CharField()

    # punted for now
    # events = models.ManyToManyField(Event)

    hosts = models.ManyToManyField(MeetingProfile)

I'm going to skip Resources for now, as I'm not convinced they are necessary. While they may help with planning a meeting, we also don't want to bog down our users with detail that may be unnecessary. This kind of feature is something I'd prefer to put in front of some usability testers, and have them figure out how useful it is. Why guess, when you can know, right?

Let's take a look at the MeetingProfile class. For one thing, we have to follow the rules for getting the profile to work with the User model. So, we need a ForeignKey to the User model. Next, we want to add some contact information. I'm thinking, for an event organizer, we'll likely want a phone number, preferably a cell phone, in order to contact the organizer in case of emergency. I think we'll need a description field, and we may want to add in an image field at some point, though that should be for a later version of the app. Dealing with images means either integrating one of the many Django image manipulation applications, or reinventing the wheel for our own purposes. I'll pass on this feature for now, as it stands to be a large post on its own. We also want to link this model to Events and Locations, but I think the link should be on the Event and Location objects, rather than on the MeetingProfile. After all, Events have organizers and attendees, not the other way around, and similarly Locations have hosts. So our end result is fairly short:

class MeetingProfile(models.Model):
    user = models.ForeignKey(User, unique=True)

    phone = models.PhoneNumberField()
    description = models.TextField()

    # punted for now
    # image = models.ImageField()

Finally, consider the Event model. An Event should have a name, a slug and a description, a set of organizers and a set of attendees. In addition, an Event should really map to RFC 2445, the iCal specification. There are a couple of Python iCal libraries out there, and we'll be picking one to use. But right now, I'm going to duck and cover, and leave the Event model for part 2. Stay tuned, this series will continue shortly.

2 Comments   Full entry


Fixed Menus For Reals

May 27, 2008

Okay, the menu is fixed for IE7, and continues to work in Safari and Firefox. It turns out that the fix is to tell the ul li structure to float left in CSS. I figured out what I was missing by comparing my local.css file to the CSS listed on A List Apart's article on Drop-Down Menus. Here's the relevant snippet from the local.css file:

ul#simple-menu{
    list-style-type:none;
    margin:0;
    padding:0;
    position:relative;
    }
ul#simple-menu li {
    float:left;
    }
ul#simple-menu li a{
    display:block;
    float:left;
    color:#1F2658;
    background:#b2b580;
    text-decoration:none;
    padding:0 9px 0 9px;
    font-size:1.1em;
    font-weight:800;
    text-transform:uppercase;
    height:3em;
    line-height:3em;
    text-shadow: 1px 1px 2px #555;
    }
ul#simple-menu li a:hover{
    background:#943F3B;
    text-shadow: 1px 1px 2px #555;
    }

I haven't bothered to test on IE6, but since the ALA article was written in 2004, I figure I'm in fairly safe territory. And, entertainingly, I don't have access to IE6 anymore with which to test it, so... ooops, oh well.

0 Comments   Full entry


Fixed menus -- Not

May 27, 2008

Happy, happy, I fixed the menus on the site. No longer do they look off-kilter using FireFox on Windows. Instead, they look decent. I reverted from a more-complicated CSS-based menu to a much simpler CSS-based menu. The sad part is, they still look bad in IE6, but ya know what? I can't actually be bothered to care, and I certainly can't be bothered to do anything about it.

Update: Damn, I spoke too soon. For whatever reason, the menu looks like a set of stairs in either IE6 or IE7. Looks fine in Safari or Firefox.

0 Comments   Full entry


Current Bugs, Minus One

May 09, 2008

I finally got my contact form working. I had a slight syntax error in my settings file, my MANAGERS was not a tuple of tuples, it was a single tuple. In short, I'd forgotten the trailing comma...

Anyhoo, it works now, so I'm pretty happy with it. Now on to the next big steps, integrating django-atompub and comment_utils.

0 Comments   Full entry


Current Bugs

April 27, 2008

Any new endeavor is bound to have a rocky start. As it stands, this weblog is no different. At the moment, the following features do not work properly:

0 Comments   Full entry


A Spooky Welcome

April 27, 2008

I am pleased to announce the grand opening of my new weblog at http://spookypony.com, which I hope will provide me with a soap box high enough to be heard over the general din. I am very happy with the design, which while somewhat odd, represents a fair amount of work on my part.

At some point, I hope to add comments. It probably won't take too terribly long, but I do have some initial issues to work out before I start work on integrating comments.

0 Comments   Full entry