Propagate model field defaults to ModelSerializer fields#9997
Open
M2004GV wants to merge 2 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Refreshed resubmission of #8130, which was closed without being merged.
ModelSerializeralready propagates a model field'sdefaultto the generated serializer field when that field participates in a uniqueness constraint (get_uniqueness_extra_kwargs), but not otherwise. This means a plainIntegerField(default=0)(with no uniqueness constraint) is generated asrequired=Falsebut with nodefault, so omitting it from the input simply drops the attribute instead of falling back to the model's default — inconsistent with how Django'sModelFormbehaves, 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'sdefaultinget_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:
OPTIONSresponses to include the default, consistent with howdefaultis already surfaced inschemas/openapi.py. Done in the second commit:SimpleMetadata.get_field_infonow includes adefaultkey 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
defaultthat is omitted from the input will now have that default appear invalidated_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 existingField.get_default()behavior.Test plan
test_default_value_used_when_field_omittedandtest_default_value_skipped_on_partial_updateintests/test_model_serializer.py, and updated therepr()regexes intest_regular_fields/test_field_optionsto reflect the newdefault=...kwarg.test_default_value_field_infoandtest_callable_default_field_infointests/test_metadata.py.docs/api-guide/fields.mddocumenting the propagation.flake8clean on changed files.