I've now gotten far enough into my application to have stubbed my toes on a few beginner's mistakes in Django and ORM schema design. Fortunately I've done this during development instead of production, so it's merely a valuable learning experience.

First, I should never make schema fields into explicit primary keys, no matter how attractive it seems and how SQL-proper it is. Especially I should not do this when the field is shown to or used by humans. Otherwise, sooner or later I will discover that either there's a typo in that field in some record or that there's some unanticipated need to change it after all. And then of course foreign keys make everyone else get heartburn, at least if you're working through Django's admin interface.

Letting Django have its invisible 'id' primary key field is much, much simpler and far more future proof, no matter how much it offends the SQL-aware portion of my brain.

(A related tragic mistake is directly linking audit records to the object that they're reporting on as a foreign key relationship, thereby insuring that either you can never delete the master object or that when you delete the master object you automatically lose all audit records associated with it.)

The second is that you cannot have an optional character or text field that is also unique (for instance, an optional login). Even if your database allows this in general (not all SQL databases allow UNIQUE fields to have several rows be NULL in the field), Django's admin interface will turn an unset field into an empty string, not a NULL, which really does have to be unique in the field.

Django's documentation covers that you really don't want to try to have fields that can be both blank and null (and what happens with character fields), but the documentation doesn't quite spell out the full consequences. Learn from my example; you really don't want to do that, even if it looks like you're getting away with it.

(If you are a particularly optimistic person, you can view this as Django saving you from making unportable assumptions about database behavior.)