Learning from Django

Edward O’Connor
http://tess.oconnor.cx/2008/merbcamp/

Who am I?

Dorky things I do with my nerdy friends

I run Django San Diego and help run the San Diego Web Standards Group.

Merb and Django

What’s a merbivore anyway?

Couldn’t find a picture of your mascot

The Djangopony.

Learning from Django: Lesson #1

Don’t let Bryan Veloso unilaterally decide on your mascot.

Terminology

MerbDjango
appproject
sliceapp
controllerview
viewtemplate

Merb and Django

AWESOME!

Lots in common

Merb team studied Django and other web frameworks

Topics

Merb Slices / Django Apps

Slices are awesome—embrace them!
This is your gateway to reusability heaven.

James Bennett's fourfold path (part 1)

Unix Philosophy

AWESOME!

Ex. MerbAuth

Separate slices for

Site as glue

Profusion of many slices

Even simple Django sites easily end up composed of a dozen apps or more!

It’s hard

import this

Namespaces are one honking great idea—let’s do more of those!

The fourfold path, cont.

Flexibility ≠ Monkeypatching

import this

Explicit is better than implicit.

Protocol-Oriented Programming

Explicitly expose how your slice operates in a controlled manner, so that your slice continues to work when such exposed bits are changed out from under you.

Think aliasing vs. public API.

ObLisp: MetaObject Protocol

AWESOME!

Other examples

Slice-centric Development

Inevitable end result: Pinax

This one goes to eleven.

Is this already upon us, in gluttonberg?

</slices>

Your router pwns

Admin interface

Generic CRUD admin UI you get for free

# admin.py
from django.contrib import admin
from djangosd.apps.blog.models import Post

admin.site.register(Post)
# urls.py
from django.conf.urls.defaults import *
from django.contrib import admin

admin.autodiscover()

urlpatterns = patterns('',
    ('^admin/(.*)', admin.site.root),
)

The admin interface is beautiful.

Autoadmin cont.

This is pretty much the awesomest thing ever…

but it’s thoroughly tied to particular ORM.

Generic Views

from django.conf.urls.defaults import *
from djangosd.apps.blog.models import Post

info_dict = {
    'queryset': Post.objects.all(),
    'date_field': 'published',
}

# ...
# ...

urlpatterns =
  patterns('django.views.generic.date_based',
    (r'^(?P<year>\d{4})/(?P<slug>[-\w]+)/$',
     'object_detail', info_dict),
    (r'^(?P<year>\d{4})/$',
     'archive_year', info_dict),
    (r'^$', 'archive_index', info_dict),
  )

N.B. “controller” vs. “view”

Syndication framework

from django.conf.urls.defaults import *
from djangosd.apps.blog.feeds \
    import LatestPosts, LatestComments

feeds = {'posts': LatestPosts,
    'comments': LatestComments,
}

urlpatterns = patterns('',
    (r'^feeds/(?P<url>.*)/$',
     'django.contrib.syndication.views.feed',
     {'feed_dict': feeds}),)

Feed objects

from django.contrib.syndication.feeds import Feed
from blog.models import Post

class LatestPosts(Feed):
    title = "Blah blah blah"
    link = "/"
    description = "Most recent posts blah."

    def items(self):
        return Post.objects.order_by('-published')[:10]

Local flavor

from django import forms
from django.contrib.localflavor.us.forms \
    import USSocialSecurityNumberField

class SomeForm(forms.Form):
    ssn = USSocialSecurityNumberField()

Also postal codes, phone numbers, region and city select boxes, etc.

Documentation

Crucial to community growth

Agnosticism

Django’s branded defaults

Thank you

Questions?

CC BY-SA 3.0