Model CharFiled with choices attribute mapped to regular Serializer CharField instead of ChoicesField when editable is set to False #8511
-
As I understand, model |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
This comment has been minimized.
This comment has been minimized.
-
The problem with the current implementation is that the corresponding schema (for example, OpenAPI) for the model field does not describe the possible values correctly. This makes the schema a bit less useful when it comes to describing fields returned via GET requests, for example. So, although @yyyyyyyan's argument above is valid, it is missing the issue with the schema:
|
Beta Was this translation helpful? Give feedback.
-
This issue affects any model field that uses class Status(models.IntegerChoices):
Active = 1, "Active"
Expired = 2, "Expired"
class Deadline(ComputedFieldsModel):
end_date = models.DateField("End")
@computed(
models.PositiveSmallIntegerField(
"Status",
choices=Status,
),
depends=[("self", ("end_date"))],
)
def status(self):
today = date.today()
if today >= self.end_date:
return Status.Expired
return Status.Active And the corresponding serializer: class DeadlineSerializer(HyperlinkedModelSerializer):
class Meta:
model = Deadline This currently generates the following OpenAPI schema (via drf-spectacular): ...
"PatchedDeadline": {
"type": "object",
"properties": {
"path": {
"type": "string",
"format": "uri",
"readOnly": true
},
"end_date": {
"type": "string",
"format": "date",
"title": "End"
},
"status": {
"type": "integer",
"readOnly": true
}
}
},
... However, we would expect (and prefer) a schema that includes the enum definition for status, like this: ...
"PatchedDeadline": {
"type": "object",
"properties": {
"path": {
"type": "string",
"format": "uri",
"readOnly": true
},
"end_date": {
"type": "string",
"format": "date",
"title": "End"
},
"status": {
"allOf": [
{
"$ref": "#/components/schemas/StatusEnum"
}
],
"readOnly": true
},
}
},
...
"StatusEnum": {
"type": "integer",
"enum": [
1,
2
]
},
... We understand that validation is intentionally skipped for non-editable fields (as handled by Django itself), but having the choices metadata in the schema is still highly valuable (e.g. for documentation, client generation, and API introspection tools). Additional it would not change the validation logic of drf. We have verified that it’s technically possible to include class DeadlineSerializer(HyperlinkedModelSerializer):
status = ChoiceField(read_only=True, choices=Status.choices)
class Meta:
model = Deadline So it would be great if this could be supported automatically without needing a manual override or workaround. We have opened a proposed fix here, and would love your feedback: Thanks again for your work on DRF! |
Beta Was this translation helpful? Give feedback.
Hi! This is by design. A
ChoiceField
is a field that can accept a value out of a limited set of choices [1]. If your field is not editable, Django assumes it's not supposed to be set [2], so the field won't show up in the admin or any ModelForm. With DRF and serializers it's the same! Since it's not supposed to be set to any value, it doesn't make sense to use aChoiceField
, because there's no need for validation.