Django rest框架嵌套序列化程序不适用于M2M关系

时间:2018-08-14 22:08:37

标签: python django serialization django-rest-framework

我的 models.py 看起来像这样:

class IP(models.Model):
    hostname = models.CharField(max_length=50, unique=True)
    ip_address = models.CharField(unique=True)

class IPGroup(models.Model):
    name = model.CharField(max_length=50, unique=True)
    ips = models.ManyToManyField(IP, through=IPGroupToIP)

class IPGroupToIP(models.Model):
    ip_group = models.ForeignKey(IPGroup)
    ip = models.ForeignKey(IP)

我的 serializers.py 看起来像这样:

class IPSerializer(serializers.ModelSerializer):
    class Meta:
        model = IP
        fields = ['id', 'host_name', 'ip_address']


class IPGroupSerializer(serializers.ModelSerializer):
    ips = IPSerializer(many=True)

    class Meta:
        model = IPGroup
        depth = 1
        fields = '__all__'

    def create(self, validated_data):
        # Pop out ips since these are M2M relations and have to be created separately
        ips_data = validated_data.pop('ips', None)
        # Create the IPGroup object 
        ip_group_obj = IPGroup.objects.create(name=validated_data['name'])

        if ips_data:
            for ip in ips_data:
                # Get the ip object id if already created or create it on the fly and save it
                ip_obj, created = IP.objects.get_or_create(host_name=ip['host_name'], ip_address=ip['ip_address'])
                # Update through table for M2M relationship
                IPGroupToIP.objects.create(ip_group_id=ip_group_obj.id, ip_id=ip_obj.id)
        return ip_group_obj

最后是我的 views.py 如下:

class IPGroupCreateView(generics.CreateAPIView):
    queryset = IPGroup.objects.get_queryset()
    serializer_class = IPGroupSerializer

这可以按预期工作,并且将以下JSON创建请求发送到API端点即可完成工作:

{
"name":"TestIPGroup1",
"ips": [{"name":"host1","value":"8.8.4.4"}, {"name":"host2","value":"8.8.8.8"}]
}

但是,如果我发送另一个具有相同IP地址的JSON创建请求,如下所示:

{
"name":"TestIPGroup2",
"ips": [{"name":"host1","value":"8.8.4.4"}, {"name":"host2","value":"8.8.8.8"}]
}

它给我一个错误,指出 IP地址已经存在。现在正在发生这种情况,因为嵌套IPSerializer的IP字段 unique 验证检查开始了。如何禁用默认字段唯一检查?我的DRF版本是3.8.2

编辑

我尝试覆盖以下方法,但似乎不起作用:

class IPGroupSerializer(serializers.ModelSerializer):
    ips = IPSerializer(many=True)

    class Meta:
        model = IPGroup
        depth = 1
        fields = '__all__'

    def run_validators(self, value):
        for validator in self.validators:
            if isinstance(validator, validators.UniqueValidator):
                self.validators.remove(validator)
        super(IPGroupSerializer, self).run_validators(value)

1 个答案:

答案 0 :(得分:1)

显式指定id字段,并将empty验证者添加为

class IPSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(validators=[])

    class Meta:
        model = IP
        fields = ['id', 'host_name', 'ip_address']



更新

class IPSerializer(serializers.ModelSerializer):
    class Meta:
        model = IP
        fields = ['id', 'host_name', 'ip_address']

    def __init__(self, *args, **kwargs):
        nested = kwargs.pop('nested', False)
        super().__init__(*args, **kwargs)
        if nested:
            self.fields.update(
                {"id": serializers.IntegerField(validators=[])}
            )


class IPGroupSerializer(serializers.ModelSerializer):
    ips = IPSerializer(many=True, nested=True)

    # Your code