如何在Django Rest Framework中处理并行PUT / PATCH请求? (覆盖问题)

问题描述 投票:1回答:1

我正在为一个uni项目开发一个Web应用程序,它是关于机场和运营商......

Problem

问题是,当我尝试以并行方式提供给数据库时,因为在我使用的json文件中有很多关于运营商和机场的条目。

当您按顺序逐个更新(PUT和PATCH)时,它正在按预期工作,但是当我尝试PUT / PATCH并行请求时,每次都会覆盖DB中的实例。

每个机场都有一个运营商列表,当我尝试通过PUT或PATCH以并行方式向该列表添加更多运营商时,它会覆盖实例以前的运营商列表

我的模特是:

class Carrier(models.Model):
    code = models.CharField(max_length=10, primary_key=True)
    name = models.TextField()

    def __str__(self):
        return self.name

class Airport(models.Model):
    code = models.CharField(max_length=10, primary_key=True)
    name = models.TextField()
    carriers = models.ManyToManyField(Carrier, related_name='airports')

    def __str__(self):
        return self.name

串行器:

class AirportListSerializer(serializers.ModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name='airport-detail')

    class Meta:
        model = models.Airport
        fields = ('code', 'name', 'url')

class AirportDetailSerializer(serializers.ModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name='airport-detail')

    class Meta:
        model = models.Airport
        fields = ('code', 'name', 'url', 'carriers')

而我的更新方法遇到问题我必须覆盖它,因为要将新数据附加到机场实例的运营商数组中:

def update(self, request, *args, **kwargs):
        instance = self.get_object()

        serializer = serializers.AirportDetailSerializer(
            instance=instance,
            data=request.data,
            context={'request': request}
        )

        if serializer.is_valid(raise_exception=True):
            # Getting the user inputed carriers after it was validated by the serializer
            carriers = set(dict(request.data)['carriers'])    
            # Adding new carriers to the current airport list of carriers without deleting the old ones
            for carrier in serializer.validated_data['carriers']:
                print(carrier)
                carriers.add(carrier)
            print('Carriers %s' % carriers)
            # Saving alterations to the db
            serializer.save(carriers=carriers)

        # Overriding the original data for more features
        data = serializer.data
        # Creating the carrier links 
        data['carriers'] = ['http://%s/api/carriers/%s/' % (request.get_host(), carrier) for carrier in data['carriers']]

        return Response(data)

DRF Browsable API中的条目示例:enter image description here

django python-3.x parallel-processing django-rest-framework api-design
1个回答
1
投票

每次调用serializer.save(carriers=carriers)时,只使用特定PUT / PATCH请求中的载波保存Airport实例...而不是将载波添加到Airport实例中。

您应该查看writable nested serializers的文档并使用单独的CarrierSerializer

在相关的说明,你的update逻辑更适合作为AirportSerializer的一部分,而不是你的观点。这使它更具可重用性。 DRF文档的这一部分是您的完美示例。

像这个伪代码改编自Albums / Tracks示例:

class AirportSerializer(serializers.ModelSerializer):
    carriers = CarrierSerializer(many=True)

    class Meta:
        model = Airport
        fields = ......

    def update(self, instance, validated_data):
        carriers_data = validated_data.pop('carriers')
        for carrier in carriers_data:
            Carrier.objects.update_or_create(airport=instance, defaults=carrier_data)
        return instance
© www.soinside.com 2019 - 2024. All rights reserved.