django-ninja
django-ninja copied to clipboard
`choices` Field Support
I noticed that Django-ninja doesn't support some fields with choices
when converted with ModelSchema
. Is there a reason why Django-ninja doesn't support these fields?
Also, I haven't yet tried, but is it feasible to extract the choices
from the model and create a custom TYPES
from ninja/orm/fields.py
, like done here https://github.com/vitalik/django-ninja/issues/694#issuecomment-1456543192 .
Below is an example of choices
not being picked up.
from ninja import NinjaAPI, Schema, ModelSchema
from .models import TestModel
api = NinjaAPI()
class TestSchema(ModelSchema):
class Meta:
model = TestModel
exclude = ['id']
@api.get("/hello")
def test(request, test: TestSchema):
return "Hello world"
from django.db import models
class TestSelections(models.TextChoices):
ONE = '1', 'one'
TWO = '2', 'two'
class TestModel(models.Model):
name = models.CharField(max_length=20)
selection = models.CharField(max_length=20, choices=TestSelections.choices)
The resulting TestSchema
and the openapi schema does not recognize the TextChoices
set as the field for selection, and will only set it as a string field. It will pick it up if we manually set a field like below.
class TestSchema(ModelSchema):
selection: TestSelections
class Meta:
model = TestModel
exclude = ['id']
Btw, I love using your Django-ninja! It makes using Django for rest apis so much easier.
(Actually I quickly came to realize that it may not be feasible with modifying TYPES
)
I have observed the same issue, I think the solution here is to use Pydantic's Enum option as described here with ModelSchema.
Yeah, it works when you manually set it. But I feel like ModelSchema should automatically pick this up.
I noticed the same issue. Setting it manually works, but it'd be nice if it did it automatically. Also, how can I make it display the "label" instead of the "value" of the TextChoices
?
For example:
class Status(models.TextChoices):
DRAFT = "draft", "Draft"
REVIEW = "review", "Review"
PUBLISHED = "published", "Published"
When setting the field in the schema manually - status: Status
- it display it as "draft", but it should display the human-readable label of "Draft" instead. This "label" functionality of Django's TextChoices is really important for localization.
To be honest I totally agree this is something that should be automatically detected from the Django field choices. It is really weird that is not happening already :(
This looks like it would have had some trouble until Django 5, because Django 4 and below required you to pass in your choices using the .choices property ex. my_type = models.CharField(max_length=20, choices=MyEnum.choices)
. The .choices property is an iterable so the name of the enum is unknown. Now that Django 5 supports just passing in the enum on its own choices=MyEnum
this is probably easier to do.