sbdchd / django-types

:doughnut: Type stubs for Django
MIT License
202 stars 63 forks source link

Allow CharField to define a generic enum type #34

Closed bellini666 closed 2 years ago

bellini666 commented 3 years ago

It would be nice to have support for this: https://docs.djangoproject.com/en/3.2/ref/models/fields/#enumeration-types

Maybe something like this:

class SomeEnum(models.TextFields):
    FOO = "foo"
    BAR = "bar"

some_enum_field = models.CharField[SomeEnum](  # note the [SomeEnum] generic here
    choices=SomeEnum.choices,
    default=SomeEnum.FOO,
)

This way the typing would know that the field reads and writes that exact enum type and not a str.

sbdchd commented 3 years ago

Interesting, playing around with it a bit, and it seems like the Django API makes it a little tricky to do this, ideally we'd pass in SomeEnum as a param, and then we could use that for the @overload.

Something like

class FooModel(models.Model):

    class BarEnum(models.TextChoices):
        FOO = "foo"
        BAR = "bar"

    some_enum_field = models.CharField(
       # something like this would allow for an @overload
        enum=BarEnum,
        default=BarEnum.FOO,
    )
sbdchd commented 3 years ago

Also by

reads and writes that exact enum type and not a str

Do you mean the set and get would be Literal["foo", "bar"]?

bellini666 commented 3 years ago

Hey @sbdchd ,

I always defined enums the old way without the models.TextChoices, and after seeing its existence yesterday I theocrafted that it would get and set the enum itself, but I just noticed that even though the set accepts the enum, the get reads it as a string, which is said :(

Having said that, allowing to declare the CharField that it get/set Literal["foo", "bar"] would be awesome! The same applies to IntegerField with choices defined.