DRF - 具有非模型write_only字段的ModelSerializer

时间:2015-02-04 13:42:15

标签: python django django-rest-framework django-serializer

我有以下Model,Serializer和View。我的目标是传递一个自定义字符串,如

referrer = "pid=email&af_sub1=ui_1120&c=xyz"

在POST方法(下面的RegisterViewSet)中然后到viewset / serializer使用这些信息填写referral_campaign,referral_media和inviting_user

所以: 1. referrer是write_only字段 2. referrer不是模型中的字段,但信息将用于填充模型中的字段

如何以DRF方式实现这一目标?

模型

class User(AbstractUser):     
    first_name = models.CharField(max_length=100, null=True, blank=True)
    last_name = models.CharField(max_length=100, null=True, blank=True)

    # social/viral feature related fields
    referral_campaign = models.CharField(default="", max_length = 200, help_text="Campaign that led to the user signup")
    referral_media_source = models.CharField(default="", max_length = 200, help_text="Campaign that led to the user signup")
    inviting_user = models.ForeignKey('self', help_text="Inviting user", null=True, blank=True)

串行

class UserSerializer(serializers.ModelSerializer):

class Meta:
    model = User
    fields = ('first_name', 'last_name',)
    write_only_fields = ('first_name', 'last_name', 'referrer')     #how to use this 'referrer' field to populate the Model fields?
    read_only_fields = ('id',)

视图

class RegisterViewSet(generics.CreateAPIView):

    model = User
    serializer_class = UserSerializer
    permission_classes = [
        permissions.AllowAny
    ]

3 个答案:

答案 0 :(得分:2)

对于新来者。 ' write_only_fields'已在DRF 3中弃用。

' extra_kwargs'是新的方式。请参阅:http://www.django-rest-framework.org/topics/3.0-announcement/#the-extra_kwargs-option

示例:

class UserSerializer(serializers.HyperlinkedModelSerializer):
    ...
    class Meta:
        model = User
        ...

        # 'write_only_fields' has been deprecated:
        #     write_only_fields = ('password',)
        extra_kwargs = {
            'password': {'write_only': True}
        }

答案 1 :(得分:1)

首先,您需要在序列化程序中定义此字段:

class UserSerializer(serializers.ModelSerializer):
    referrer = serializers.CharField(max_length=300, allow_blank=True)
    class Meta:
        model = User
        fields = ('id', 'first_name', 'last_name', 'referrer')
        write_only_fields = ('first_name', 'last_name', 'referrer')     #how to use this 'referrer' field to populate the Model fields?
        read_only_fields = ('id',)

(我不确定你在write_only_fields中是否需要'first_name','last_name',因为这意味着你只会获得ID作为回应,但这取决于你的要求)

现在,您需要覆盖序列化程序restore_object方法:

def restore_object(self, attrs, instance=None):
    referrer = attrs.pop('referrer')
    # parse referrer to referral_campaign, referral_media_source, inviting_user 
    ...
    instance = super(UserSerializer, self).restore_object(attrs, instance=instance)
    instance.referral_campaign = referral_campaign
    instance.referral_media_source = referral_media_source
    instance.inviting_user = inviting_user
    return instance

(此答案假定为DRF 2)

答案 2 :(得分:1)

对于DRF3,

class UserSerializer(serializers.ModelSerializer):
    referrer = serializers.CharField(max_length=300, allow_blank=True, write_only=True)

    class Meta:
        model = User
        fields = ('id', 'first_name', 'last_name', 'referrer')

    def validate(self, attrs):
        # do your stuff
        attrs.pop('referer', None)  # avoid sending it back to model creation
        return attrs

answer