Django Rest Framework with ChoiceField

前端 未结 8 1910
轮回少年
轮回少年 2020-12-02 06:01

I have a few fields in my user model that are choice fields and am trying to figure out how to best implement that into Django Rest Framework.

Below is some simplifi

相关标签:
8条回答
  • 2020-12-02 06:35

    I suggest to use django-models-utils with a custom DRF serializer field

    Code becomes:

    # models.py
    from model_utils import Choices
    
    class User(AbstractUser):
        GENDER = Choices(
           ('M', 'Male'),
           ('F', 'Female'),
        )
    
        gender = models.CharField(max_length=1, choices=GENDER, default=GENDER.M)
    
    
    # serializers.py 
    from rest_framework import serializers
    
    class ChoicesField(serializers.Field):
        def __init__(self, choices, **kwargs):
            self._choices = choices
            super(ChoicesField, self).__init__(**kwargs)
    
        def to_representation(self, obj):
            return self._choices[obj]
    
        def to_internal_value(self, data):
            return getattr(self._choices, data)
    
    class UserSerializer(serializers.ModelSerializer):
        gender = ChoicesField(choices=User.GENDER)
    
        class Meta:
            model = User
    
    # viewsets.py
    class UserViewSet(viewsets.ModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserSerializer
    
    0 讨论(0)
  • 2020-12-02 06:36

    An update for this thread, in the latest versions of DRF there is actually a ChoiceField.

    So all you need to do if you want to return the display_name is to subclass ChoiceField to_representation method like this:

    from django.contrib.auth import get_user_model
    from rest_framework import serializers
    
    User = get_user_model()
    
    class ChoiceField(serializers.ChoiceField):
    
        def to_representation(self, obj):
            if obj == '' and self.allow_blank:
                return obj
            return self._choices[obj]
    
        def to_internal_value(self, data):
            # To support inserts with the value
            if data == '' and self.allow_blank:
                return ''
    
            for key, val in self._choices.items():
                if val == data:
                    return key
            self.fail('invalid_choice', input=data)
    
    
    class UserSerializer(serializers.ModelSerializer):
        gender = ChoiceField(choices=User.GENDER_CHOICES)
    
        class Meta:
            model = User
    

    So there is no need to change the __init__ method or add any additional package.

    0 讨论(0)
提交回复
热议问题