Django Rest 框架选择字段序列化器

Den*_*din 4 python django-rest-framework

使用 Django Rest Framework 3.6.3,我的模型中有一个选择 CharField:

# models.py
class User(AbstractUser):
    GENDER_CHOICES = (
        ('M', 'Male'),
        ('F', 'Female'),
    )

    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)

# viewsets.py
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
Run Code Online (Sandbox Code Playgroud)

我正在发布到端点:

 { 'gender': 'M' }
Run Code Online (Sandbox Code Playgroud)

当我获取端点时,我希望它显示:

{ 'gender': 'Male' }
Run Code Online (Sandbox Code Playgroud)

使用以下序列化程序,它显示选择的显示值(男性)而不是值(M),但它不保存:

# serializers.py 
class UserSerializer(serializers.ModelSerializer):
    # for some reason on save, gender is None??
    gender = serializers.SerializerMethodField()

    class Meta:
        model = User

    def get_gender(self, obj):
        return obj.get_gender_display()
Run Code Online (Sandbox Code Playgroud)

如果我添加一个to_internal_value方法,那么它可以正常工作(显示性别选择显示值,但也保存:

# serializers.py 
class UserSerializer(serializers.ModelSerializer):
    gender = serializers.SerializerMethodField()

    class Meta:
        model = User

    def get_gender(self, obj):
        return obj.get_gender_display()

    def to_internal_value(self, data):
        # if I add a to_internal_value that does nothing, it saves??
        return data
Run Code Online (Sandbox Code Playgroud)

为什么这有效?我应该有更明显的方式来写这个吗?

Lin*_*via 8

覆盖to_internal_value之所以有效,是因为您绕过了每个字段调用to_internal_value

另一种解决方案是:

class UserSerializer(serializers.ModelSerializer):
    gender = serializers.ChoiceField(choices=User.GENDER_CHOICES)

    class Meta:
        model = User
Run Code Online (Sandbox Code Playgroud)