【问题标题】:Django Rest Framework - Nested Serializer are lazy loaded?Django Rest Framework - 嵌套序列化程序是延迟加载的?
【发布时间】:2015-04-13 14:51:06
【问题描述】:

我很喜欢使用 Django Rest Framework,并且从中获得了很多乐趣。 但是有一件事情让我感到不安。我有一个模型,在这个模型中有很多外键。即:

class Order(models.Model):
    bought_by = models.ForeignKey(User, related_name='bought_orders')
    bought_on = models.DateTimeField(default=datetime.datetime.now, blank=True)
    category = models.ForeignKey(OrderCategory, related_name='orders')
    article = models.ForeignKey(Article, related_name='orders')
    supplier = models.ForeignKey(Supplier, related_name='orders')
    purpose = models.CharField(null=True, blank=True, max_length=255)
    payment_method = models.ForeignKey(PaymentMethod, related_name='orders')
    order_number = models.CharField(max_length=255)
    delivery_received_on = models.DateTimeField(null=True, blank=True)
    delivery_received_by = models.ForeignKey(User, null=True, blank=True, related_name='received_orders')
    tags = TaggableManager(blank=True)

所以我使用了好的 ModelSerializer,顺便说一下,我使用了嵌套的序列化器,即:

class ReadOrderSerializer(ModelSerializer):
    created = DateTimeField()
    updated = DateTimeField()
    bought_by = UserSerializer()
    category = OrderCategorySerializer()
    article = ArticleSerializer()
    supplier = SupplierSerializer()
    payment_method = PaymentMethodSerializer()
    tags = TagListSerializerField()
    invoice_documents = InvoiceDocumentSerializer(many=True)

问题在于,仅 50 个订单的请求大约需要 1.7 秒。 好吧,这出乎意料……我打开了我的 Django 调试工具并查看了 sql 语句。 Django Rest Framework 或 Django 为每个订单打开一个新连接并执行一个 select 语句。

有没有办法解决这个问题? 关闭延迟加载或我可以在序列化程序中更改的内容?

非常感谢!

【问题讨论】:

    标签: python django serialization django-rest-framework


    【解决方案1】:

    您的问题来自查询集,而不是序列化程序。默认情况下,Django 查询集不遵循关系,因此不会填充相关字段。 为了解决这个问题,您必须更改您的查询集以使用 select_related 用于 OneToOneForeignKey 字段和 prefetch_related 用于 ManyToMany 字段。

    假设您正在使用 DRF ViewSets,您可以将 OrderViewSet 中的 get_queryset 方法更改为类似的内容:

    def get_queryset(self):
        return Order.objects.select_related(
                'bought_by', 'category', 'article', 'supplier',
                'payment_method', 'delivery_received_by'
            ).prefetch_related(
                'tags', 'invoice_documents'
            )
    

    【讨论】:

    • 非常感谢!这对我帮助很大 :) 祝你有美好的一天
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-09
    • 2018-07-06
    • 1970-01-01
    • 2014-08-20
    • 1970-01-01
    • 2018-05-20
    • 2014-12-21
    相关资源
    最近更新 更多