With the gracious help of Dane Springmeyer, I recently got Mapnik up and running on my Mac, so naturally the first thing I wanted to do was to plot iNaturalist observations. Mapnik will talk with a PostGIS database just fine, but it wont’t pull points from a MySQL database table, at least not directly. What it does support, though, is the all-powerful OGR. Back when I used to use Mapserver, I had used OGR a few times to act as a bridge between simple lat/lon columns in a MySQL table and Mapserver (great description here), so I figured the same would be possible in Mapnik.

Read the rest of this entry »

Django 1.0 is coming, and it’s bringing needed but backwards-incompatible changes to the admin site, ostensibly the best thing about Django.  One problem I’ve run into while migrating to the new version is inline editing of related classes in existing classes.  For example, it’s pretty common (and recommended) to “extend” Django’s built-in User model by creating your own, related Profile model.  For the old admin site, you specified the ability to edit a relate Profile in the User form in the Profile model:

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

That was simple, but kinda quirky. Changing the way the User form looks by changing the related Profile model? Weird. BUT, it did let you make changes to the User model w/o mucking with the built in Django code.

The new way of doing things is to specify all your admin site options in a separate file, and inline editing is now a little more reasonable: if you want to edit related objects in a model’s form, you specify that in that model’s admin options. But this means you need to alter Django’s built-in User model’s admin options, which could mean muckiness. So here’s what I did in my myapp/admin.py:

from django.contrib import admin
from django.contrib.auth.models import User
from myapp.models import *
class ProfileAdmin(admin.ModelAdmin):
    # just some stuff for my profile forms
    filter_horizontal = ('teams',)
    radio_fields = {'appointment': admin.HORIZONTAL}
    list_display = ('user', 'picture', 'appointment', 'affiliation')
admin.site.register(Profile, ProfileAdmin)
# need to make an inline class...  ick
class ProfileInline(admin.StackedInline):
    model = Profile
    max_num = 1
# the meat: grab the existing UserAdmin class, modify it, unregister User,
# and re-register User with the modified UserAdmin
UserAdmin = admin.site._registry[User].__class__
UserAdmin.inlines = [ProfileInline,]
admin.site.register(User, UserAdmin)

Took me a while to realize admin.site._registry held instances of the ModelAdmin classes, not the classes themselves. This technique also assumes that User gets registered with the admin site before you run this code. I’m guessing the order in which admin.autodiscover() registers models is the same as the INSTALLED_APPS setting in settings.py.