Currently, db_default has no effect on model forms. I was mistakenly under the assumption that it would behave somewhat similarly to default (if default is not set in addition to db_default).
There are 3 behaviours that I think we should be considered for either alteration or clarification in the docs:
1. Supplying an initial value
When default is set, the model form’s field gets it’s initial set to the default. This makes sense for default but should it set it for db_default if we have simple scalar values like Value("asdf")?
I’m not a big fan of too much magic so I’d probably lean towards no - and document this saying that if you want the default value to show on the form then it would need to be declared on the form or via default if that makes sense to set that on top of db_default.
2. Setting the field’s required flag
Currently a non-null field with db_default set has required=True. This can be solved with blank=True on the model field but perhaps again the model form field generation could be changed? If not then some doc updates to explain this might be nice.
3. Setting the form field’s empty value
When a form is submitted, the form field’s empty value is passed to the ORM and db_default is never used. I found that if setting a field’s empty_value=DatabaseDefault() then this allows delegating the value to db_default.
Currently users need to manually create a model form and set the empty_value but this isn’t an obvious solution because DatabaseDefault is currently undocumented.
Since this is a non-obvious, I strongly recommend that either DatabaseDefault is documented; or we could add this small change to Django in db.models.fields.Field.formfield():
def formfield(self, …):
…
if self.db_default is not NOT_PROVIDED:
defaults["empty_value"] = DatabaseDefault()
…
Another option may be to include DatabaseDefault in the field’s initial upon rendering but this is a non-trivial approach as we’d need to manage it (eg not rendering it) and additionally Field.has_default() vs Field.get_default() both deal with db_default differently.