Django REST Framework序列化POST速度很慢

时间:2018-11-18 19:38:21

标签: python django django-rest-framework

我正在Django 2.1.1和Python 3.6.5上运行,并且正在执行相当大的POST操作(32,000个JSON对象)。我有以下内容:

型号:

class Data(models.Model):
    investigation = models.ForeignKey(Investigation)
    usage = models.FloatField()
    sector = models.CharField(max_length=100, blank=False, default='')
    cost = models.FloatField()
    demand = models.FloatField()

序列化器:

class DataSerializer(serializers.ModelSerializer):
    class Meta:
        model = Data
        fields = ('investigation', 'usage', 'sector', 'cost', 'demand')

查看:

class DataView(generics.CreateAPIView):
    def create(self, request, pk, format=None):
        data_serializer = DataSerializer(data=request.data, many=True)
        if data_serializer.is_valid():
            data_serializer.save()

问题出在is_valid()和save()两个步骤上,它们分别对32,000个对象中的每一个触发单独的查询。

我花了很长时间研究这个问题,我猜is_valid()步很慢,因为N + 1查询问题,因为每次都要查询外键(尽管我可以这是错误的!),但我不知道如何在此框架中实现prefetch_related方法。

save()步骤(这是最慢的部分)显然需要在一个查询(可能是bulk_create)中完成,但是我找不到在哪里添加bulk_create步骤。我读过{{3} },但仍然不是答案中最明智的人。正如问题所示,我试图创建一个ListSerializer,但是对象似乎仍然被一个接一个地序列化。

任何指针将不胜感激。

2 个答案:

答案 0 :(得分:0)

您可以尝试如下重写序列化器的create方法:

def create(self, request):
    is_many = True if isinstance(request.data, list) else False

    serializer = self.get_serializer(data=request.data, many=is_many)
    serializer.is_valid(raise_exception=True)
    self.perform_create(serializer)
    headers = self.get_success_headers(serializer.data)
    return Response(serializer.data, status=status.HTTP_201_CREATED,headers=headers)

答案 1 :(得分:0)

一种可能的解决方案是在使用序列化程序验证数据之后执行Django ORM $("#personal").click(function() { if ($(this).is(":checked")) { alert('Personal'); /* var validator = $("#register_france").validate(); validator.resetForm(); */ } } ); 。您的视图将如下所示:

bulk_create()

或仅以下一项,如果您想要单线:

class DataView(generics.CreateAPIView):
    def create(self, request, pk, format=None):
        data_serializer = DataSerializer(data=request.data, many=True)
        if data_serializer.is_valid():
            data_objects = []
            for data_object_info in data_serializer.validated_data:
                data_objects.append(Data(**data_object_info))
            Data.objects.bulk_create(data_objects)

如果不想使视图混乱,则可以编写一个执行验证(使用序列化程序)和创建的类或方法。然后,您可以在视图内部使用它。