Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

As I understand, model CharField with choices attribute should be mapped to Serializer ChoicesField, which happens in most cases, but the problem is when model CharField has editable=False, the line at rest_framework/utils/field_mapping.py:98 checks if the field has editable set to False then ignores all other checks, and one of the ignored check is the check that adds the choices attribute to serializer kwargs, which will later be used to determine the serializer field to be used.

You must be logged in to vote

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 a ChoiceField, because there's no need for validation.

Replies: 3 comments · 2 replies

This comment has been minimized.

Comment options

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:

Since it's not supposed to be set to any value, it doesn't make sense to use a ChoiceField, because there's no need for validation.

You must be logged in to vote
2 replies
@yyyyyyyan

This comment has been minimized.

@vakorol
Comment options

Yes, of course. I am using an extended DRF's AutoSchema, though. And my problem is that tools provided by DRF iself create a schema that is incomplete..

Comment options

This issue affects any model field that uses choices but is marked as editable=False. A common case is when using django-computedfields like in the following example:

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 choices on read-only fields like this:

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:
BonaFideIT/django-rest-framework@main...BonaFideIT-patch-1

Thanks again for your work on DRF!

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
4 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.