2015-04-13 2 views
2

Я прекрасно использую Django Rest Framework и получаю массу удовольствия от этого. Но есть одна вещь, которая меня беспокоит. У меня есть модель, и в этой модели много внешних клавиш. то есть: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) 

Проблема заключается в том, что запрос занимает около 1,7 секунд, только 50 заказа. Ладно, это было неожиданно ... Я открыл свой инструмент отладки Django и посмотрел на операторы sql. Django Rest Framework или Django открывает для каждого заказа новое соединение и делает оператор select.

Есть ли способ преодолеть проблему? Отключить ленивую загрузку или что-то, что я могу изменить в своих сериализаторах?

спасибо!

ответ

6

Ваша проблема связана с запросом, а не с сериализатором. По умолчанию запросы Django не соответствуют отношениям, поэтому связанные поля не заполняются. Для того чтобы исправить это, вы должны изменить свой запрос на использование select_related для OneToOne и ForeignKey полей и prefetch_related для полей ManyToMany.

Так позволяет сказать, что вы используете DRF ViewSets, вы можете изменить метод get_queryset в OrderViewSet к чему-то вроде этого:

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

Большое спасибо! Это очень помогло мне :) У меня отличный день –