Как оптимизировать сериализацию данных моделей в Django Rest Framework? - PullRequest
0 голосов
/ 11 мая 2018

Мне нужен совет. Иногда возникают ситуации, когда в API мне нужно получить много данных из некоторых таблиц БД. И когда я пытаюсь получить все данные - это занимает много времени. Поэтому я использую небольшой велосипед для извлечения данных в одном запросе.

Пример:

class SomeModelSerializer(serializers.ModelSerializer):
    related_name1 = serializers.SerializerMethodField()
    related_name2 = serializers.SerializerMethodField()
    related_name3 = serializers.SerializerMethodField()

    def get_related_name1(self, obj):
        return self.values[obj.id].get('related_table1__name')

    def get_related_name2(self, obj):
        return self.values[obj.id].get('related_table1__related_table2__name')

    def get_related_name3(self, obj):
        return self.values[obj.id].get('related_table3__name')

    def __init__(self, *args, **kwargs):
        super(SomeModelSerializer, self).__init__(*args, **kwargs)
        # Collect all necessary data from BD.
        self.values = {}
        if self.instance:
            for some_model_values in self.instance.values(
                'id',
                'related_table1__name',
                'related_table1__related_table2__name',
                'related_table3__name'
            ).iterator():
                self.values[some_model_values['id']] = some_model_values

    class Meta:
        model = SomeModel
        fields = ('id', 'related_name1', 'related_name2', 'related_name3')

Отлично работает в ситуациях, когда необходимо извлечь много данных, но это занимает больше времени при кодировании, чем простой сериализатор. Это хорошая идея для оптимизации извлечения данных, или у вас есть другие решения для этой ситуации?

Это решение делает 2 запроса к БД для любого набора запросов.

Ответы [ 3 ]

0 голосов
/ 11 мая 2018
class SomeModelSerializer(serializers.ModelSerializer):
     value1 = serializer.CharField(source='related_table1.name', read_only=True)
     value2 = serializer.CharField(source='related_table1.related_table2.name')
     ............
     # and so on
     class Meta:
         model = ModelName
         fields = (
             'value1',
             'value2',
             ....
         )

Я думаю, это не так много, чтобы написать это Информация об этом: http://www.django -rest-framework.org / api-guide / fields / # source

0 голосов
/ 12 мая 2018

Вы пытались использовать prefetch_related в view / viewset, который использует SomeModelSerializer?Что-то вроде

from rest_framework import viewsets

from myapp.models import SomeModel
from myapp.api.v1.serializers import SomeModelSerializer


class SomeModelViewSet(viewsets.ModelViewSet):
    serializer_class = SomeModelSerializer
    queryset = SomeModel.objects.prefetch_related(
        'related_table1',
        'related_table1__related_table2',
        'related_table3',
    )
0 голосов
/ 11 мая 2018

мы можем просто переопределить метод to_representation в сериализаторе.

class SomeModelSerializer(serializers.ModelSerializer):

  def to_representation(self, instance):
    data = super(SomeModelSerializer, self).to_representation(instance)
    data.update({
       'related_name1': instance.related_table1.name,
       'related_name2': instance.related_table2.name
       # more fields & values
    })
    return data

  class Meta:
    model = SomeModel
    fields = ('id',)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...