Skip to content

Propagate model field defaults to ModelSerializer fields#9997

Open
M2004GV wants to merge 2 commits into
encode:mainfrom
M2004GV:propagate-model-field-defaults
Open

Propagate model field defaults to ModelSerializer fields#9997
M2004GV wants to merge 2 commits into
encode:mainfrom
M2004GV:propagate-model-field-defaults

Conversation

@M2004GV

@M2004GV M2004GV commented Jul 3, 2026

Copy link
Copy Markdown

Description

Refreshed resubmission of #8130, which was closed without being merged.

ModelSerializer already propagates a model field's default to the generated serializer field when that field participates in a uniqueness constraint (get_uniqueness_extra_kwargs), but not otherwise. This means a plain IntegerField(default=0) (with no uniqueness constraint) is generated as required=False but with no default, so omitting it from the input simply drops the attribute instead of falling back to the model's default — inconsistent with how Django's ModelForm behaves, and surprising given DRF already does the equivalent for unique-constrained fields.

This PR generalizes that existing behavior: whenever model_field.has_default(), the value is passed through as the serializer field's default in get_field_kwargs.

Closes #7469. Related to #2683 / #7489.

Addressing prior review feedback

On the original PR, @auvipy asked for two things before it could be accepted:

  1. Rebase with a fresh approach — done here as a clean two-commit PR.
  2. Update OPTIONS responses to include the default, consistent with how default is already surfaced in schemas/openapi.py. Done in the second commit: SimpleMetadata.get_field_info now includes a default key for any non-callable field default.

Behavior change

The only user-visible behavior change is for non-partial updates/creates: a field with a model-level default that is omitted from the input will now have that default appear in validated_data, matching what already happens for fields covered by uniqueness constraints. Partial updates (partial=True) are unaffected — defaults are still skipped in that case, per existing Field.get_default() behavior.

Test plan

  • Added test_default_value_used_when_field_omitted and test_default_value_skipped_on_partial_update in tests/test_model_serializer.py, and updated the repr() regexes in test_regular_fields / test_field_options to reflect the new default=... kwarg.
  • Added test_default_value_field_info and test_callable_default_field_info in tests/test_metadata.py.
  • Added a note to docs/api-guide/fields.md documenting the propagation.
  • Full test suite passes against both Django 5.2 and Django main (6.2 dev): 1562 passed, 0 failed.
  • flake8 clean on changed files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ModelSerializer generate ChoicesField will discard default parameter

1 participant