首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何处理Django Rest框架中的并行PUT/修补程序请求?(覆盖问题)

如何处理Django Rest框架中的并行PUT/修补程序请求?(覆盖问题)
EN

Stack Overflow用户
提问于 2019-03-16 11:01:26
回答 1查看 702关注 0票数 1

我正在为一个uni项目开发一个网络应用程序,它是关于机场和航空公司的.

问题

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

当您逐个更新(PUT和修补程序)时,它按应有的方式工作,但当我尝试PUT/PATCH并行请求时,DB中的实例每次都会被覆盖。

每个机场都有一个运营商列表,当我试图通过PUT或修补程序将更多的运营商添加到该列表时,它将覆盖以前的运营商列表

我的模特是:

代码语言:javascript
运行
复制
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

序列化程序:

代码语言:javascript
运行
复制
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')

我的更新方法有问题,我不得不重写它,因为要将新数据附加到机场实例的载体数组中:

代码语言:javascript
运行
复制
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可浏览API中的条目示例:

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-16 17:43:02

每次调用serializer.save(carriers=carriers)时,都只使用特定PUT/修补程序request...rather中的载波来保存Airport实例,而不是向Airport实例中添加载波。

您应该查看可写嵌套序列化器的文档,并使用单独的CarrierSerializer

与此相关的是,update逻辑更适合作为AirportSerializer的一部分,而不是视图。这使得它更可重用。DRF文档的这一部分对您来说是最好的例子。

类似于从专辑/曲目示例中改编的伪代码:

代码语言:javascript
运行
复制
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
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55196009

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档