For the drafts side, what we do (LedgerSMB. PostgreSQL) is use a bool "approved" column or some approval information (where NULL means draft, for example "approved_by" or "approved_at").
I don't know the quirks of MySQL check constraints too well, but in PostgreSQL you can condition check constraints on the value in a field, something like:
CHECK (approved is not true or title is not null). This makes it impossible to approve something that has not had everything filled on. We don't do this generally because approval is supposed to be all or nothing, but there are a few areas where something like this is done.