DRF - 具有非模型 write_only 字段的 ModelSerializer
DRF - ModelSerializer with a non-model write_only field
我有以下模型、序列化程序和视图。我的目标是传递自定义字符串,例如
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
]
首先,你需要在序列化器中定义这个字段:
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',)
(我不太确定你是否需要 'first_name'、'last_name' in write_only_fields,因为这意味着你只会得到 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)
对于新来者。 '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}
}
对于 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 super().validate(attrs)
从这个这个
我有以下模型、序列化程序和视图。我的目标是传递自定义字符串,例如
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
]
首先,你需要在序列化器中定义这个字段:
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',)
(我不太确定你是否需要 'first_name'、'last_name' in write_only_fields,因为这意味着你只会得到 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)
对于新来者。 '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}
}
对于 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 super().validate(attrs)
从这个这个