-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix choices in ChoiceField to support IntEnum #8955
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
besides, this will need unit test coverage
@@ -1397,7 +1397,8 @@ def __init__(self, choices, **kwargs): | |||
def to_internal_value(self, data): | |||
if data == '' and self.allow_blank: | |||
return '' | |||
|
|||
if isinstance(data, Enum) and str(data) != str(data.value): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from the test failures it seems that Enum is not defined. you might forgot to import it? or could you check what is the issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, I have added the import statement now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why you are removing the django compatibility support codes here if isinstance(data, (IntegerChoices, TextChoices)) and str(data) !=
str(data.value):
3ca5d08
to
b8926b0
Compare
@@ -1397,7 +1398,8 @@ def __init__(self, choices, **kwargs): | |||
def to_internal_value(self, data): | |||
if data == '' and self.allow_blank: | |||
return '' | |||
|
|||
if isinstance(data, Enum) and str(data) != str(data.value): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you please add unit test coverage for the changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the case where the enum values need to be integers is extremely common, Django provides an IntegerChoices class. For example:
class Card(models.Model):
class Suit(models.IntegerChoices):
DIAMOND = 1
SPADE = 2
HEART = 3
CLUB = 4
suit = models.IntegerField(choices=Suit.choices)
did you check this?
https://docs.djangoproject.com/en/3.2/ref/models/fields/#enumeration-types
Thanks for your suggestion, I use the class Enum implemented in python standard library first, and then I found that rest_framework is suitable for Enum. |
this a django extension and should be using what django provides first |
please use built in django feature here |
closing in favor of #8968 |
@encode/django-rest-framework hello team, should we consider supporting python Enum directly beside the django built in ones? |
that is a django compat fix. If anyone want to support direct python enum, we need to rebase this PR :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you please rebase it again?
8999b29
to
a4e1038
Compare
@auvipy ok, I have rebased it. |
@@ -1397,7 +1397,8 @@ def __init__(self, choices, **kwargs): | |||
def to_internal_value(self, data): | |||
if data == '' and self.allow_blank: | |||
return '' | |||
|
|||
if isinstance(data, Enum) and str(data) != str(data.value): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why you are removing the django compatibility support codes here if isinstance(data, (IntegerChoices, TextChoices)) and str(data) !=
str(data.value):
@@ -1414,11 +1411,8 @@ def to_internal_value(self, data): | |||
def to_representation(self, value): | |||
if value in ('', None): | |||
return value | |||
|
|||
if isinstance(value, (IntegerChoices, TextChoices)) and str(value) != \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same goes for this. we are not going to remove django compatibility features.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should make it clear.
if isinstance(value, (IntegerChoices, TextChoices)) and str(value) != \
in #8986 not resolve the problem, and this if
judgment will never be executed with the IntegerChoices and TextChoices.
Because this problem only occurs in the python version little than 3.11 and use Enum as base class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add if isinstance(data, Enum) and str(data) != str(data.value):
just enhances the Enum support for python version little than 3.11.
if isinstance(value, (IntegerChoices, TextChoices)) and str(value) != \
has not effect when users use IntegerChoices or TextChoices, because str(value) always equal to value.value according to 8740ff334ae3e001514c42ac1fb63a5e4cfa5cd1, but user swill still meet the problem when they use Enum, because that if
judgment not solve the problem of IntEnum in different python version.
tests/test_fields.py
Outdated
@@ -1875,26 +1877,26 @@ def test_edit_choices(self): | |||
field.run_validation(2) | |||
assert exc_info.value.detail == ['"2" is not a valid choice.'] | |||
|
|||
def test_integer_choices(self): | |||
class ChoiceCase(IntegerChoices): | |||
def test_enum_choices(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would make sense to add this new test in addition to keeping the old IntegerChoices
test just to ensure we don't have regressions in future versions of Django if they decide to do something special with that class.
Hey Burson! you were suggested to add new tests beside keeping the old tests using django specific class. see: It would make sense to add this new test in addition to keeping the old IntegerChoices test just to ensure we don't have regressions in future versions of Django if they decide to do something special with that class. |
6086601
to
b043df8
Compare
Python support Enum in version 3.4, but changed __str__ to int.__str__ until version 3.11 to better support the replacement of existing constants use-case. [https://docs.python.org/3/library/enum.html#enum.IntEnum](https://docs.python.org/3/library/enum.html#enum.IntEnum) rest_frame work support Python 3.6+, this commit will support the Enum in choices of Field.
@auvipy New test has added, and keeping the old tests. |
Thanks Burson! sorry for the initial over sight! |
Thanks Asif Saif Uddin for your patient guidance and valuable insights. |
Python support Enum in version 3.4, but changed __str__ to int.__str__ until version 3.11 to better support the replacement of existing constants use-case. [https://docs.python.org/3/library/enum.html#enum.IntEnum](https://docs.python.org/3/library/enum.html#enum.IntEnum) rest_frame work support Python 3.6+, this commit will support the Enum in choices of Field.
hey, we might introduce some regressions, can you please check? #9388 |
Description
Python support Enum in version 3.4, but changed
__str__
toint.__str__
until version 3.11 to better support the replacement of existing constants use-case. https://docs.python.org/3/library/enum.html#enum.IntEnumrest_framework support Python 3.6+, this commit will support the Enum as datatype of choices in Field.
Discussions: #8945