我已经定义了一个这样的序列化器:
class ActivitySerializer(serializers.ModelSerializer):
activity_project = serializers.SlugRelatedField(queryset=Project.objects.all(), slug_field='project_name')
activity_tags = serializers.SlugRelatedField(queryset=Tag.objects.all(), slug_field='tag_name', many=True)
class Meta:
model = Activity
fields = ('activity_name', 'activity_description', 'activity_status', 'activity_completion_percent', 'activity_due_date', 'activity_project', 'activity_tags',)
现在,如果我插入一个在数据库中不存在的activity_tag,我会收到验证错误“
{
"activity_tags": [
"Object with tag_name=test does not exist."
]
}
我想创建一个验证方法,如果它不存在,则在数据库中添加标记。 我尝试过使用
def validate(self, attrs):
....
方法,但显然对于一个slug字段,有一个方法在此之前被调用。
有人能指出我应该使用的正确方法吗?是否可以在相应的视图中调用此方法?
答案 0 :(得分:1)
我认为您需要创建一个嵌套的序列化程序才能实现此功能。这是完全未经测试的,并且不在我的头顶,但也许是这样的:
class ActivityTagFieldSerializer(serializer.ModelSerializer):
tag_name = serializers.SlugField()
class Meta:
model = Tag
fields = ('tag_name')
class ActivitySerializer(serializer.ModelSerializer):
activity_tags = ActivityTagFieldSerializer(many=True)
class Meta:
model = Activity
fields = ('activity_tags', 'activity_project', ...)
def create(self, validated_data):
tags = validated_data.pop('activity_tags')
activity = Activity.objects.create(**validated_data)
for tag in tags:
try:
tag_to_add = Tag.objects.get(**tag)
except:
tag_to_add = Tag.objects.create(**tag)
activity.activity_tags.add(tag_to_add)
return activity
的API指南
答案 1 :(得分:0)
我通过子类化SlugRelatedField并重写“ to_internal_value”方法来做到这一点。在原始实现中,此方法尝试从查询集中获取对象,如果不存在对象,则验证失败。因此,不是调用“ get”方法,而是调用“ get_or_create”:
class CustomSlugRelatedField(serializers.SlugRelatedField):
def to_internal_value(self, data):
try:
obj, created = self.get_queryset().get_or_create(**{self.slug_field: data})
return obj
except (TypeError, ValueError):
self.fail('invalid')