Как я могу улучшить производительность разбивки на страницы в нескольких наборах запросов django? - PullRequest
2 голосов
/ 07 февраля 2020

У меня есть 2 набора запросов:

queryset_primary = PrimaryUserSerializer(FileUpload.objects.all().order_by('name'), many=True, context=context).data
queryset_secondary = MemberSerializer(Members.objects.all().order_by('member_name'), many=True, context=context).data

Оба имеют разные ключи .. так что я повторил оба набора запросов:

    response = []
    for primary in queryset_primary:
        # name_pri=primary['primary_user_id']
        new_data={ 
            'user_id' : primary['primary_user_id'],
            'name': primary['name'],
        }
        response.append(new_data)

    for secondary in queryset_secondary:
        new_data={
            'user_id' : secondary['secondary_user_id'],
            'name': secondary['member_name'],
        }

Снова я использовал обычный сериализатор с похожими ключами в нем , для нумерации страниц:

    responses = self.paginate_queryset(response)
    if responses is not None:
        serializer = CommonUserSerializer(responses,many=True)
        data = {
            'code': 200,
            'status': "OK",
        }
        page_nated_data = self.get_paginated_response(serializer.data).data
        data.update(page_nated_data)
        data['response'] = data.pop('results')
        return Response(data)

Это занимает всего 8 секунд времени загрузки.

Как я могу сократить время загрузки API?

Ответы [ 2 ]

0 голосов
/ 07 февраля 2020

Посмотрите на .values() в ORM:

https://docs.djangoproject.com/en/3.0/ref/models/querysets/#values

Members.objects.all().order_by('member_name').values()

Это должно дать вам QuerySet, который возвращает словари, а не экземпляры модели, при использовании в качестве итерируемого.

Вы можете связать это с:

from django.http import JsonResponse

def some_view(request):
    data = list(Members.objects.all().order_by('member_name').values()) # Use list(), because QuerySet is not JSON serializable by default!
    return JsonResponse(data, safe=False)

Более конкретно c к вашему вопросу:

from rest_framework import status
from rest_framework.response import Response

def some_view(request):
    merged = []

    merged.append(
        list(Members.objects.all().order_by('member_name').values('user_id'. 'name')) + list(FileUpload.objects.all().order_by('name').values('user_id'. 'name'))
    )

    responses = self.paginate_queryset(merged)
    if responses is not None:
        serializer = CommonUserSerializer(responses, many=True)

        data = {
            'success': true,
        }
        paginated_data = self.get_paginated_response(serializer.data).data
        data.update(paginated_data)
        data['response'] = data.pop('results')
        return Response(data, status=status.HTTP_200_OK)

Вы Вам также понадобится сделать annotations(), чтобы ваши атрибуты user_id стали primary_user_id и secondary_user_id

Гораздо эффективнее!

0 голосов
/ 07 февраля 2020

При показе объемных данных следует по возможности избегать моделей и сериализаторов. Взгляните на параметр Django ORM .values ​​(), чтобы сделать выбор c. Попробуйте построить свои собственные структуры для сериализации json. Я также избегал бы вложения вложенных данных в ваши структуры (особенно в представлениях списка). Может оказаться гораздо дешевле дважды позвонить клиенту или отфильтровать ваш API, а затем вернуть «полные» данные сразу.

Вы пытались профилировать указанный вызов API c? Панель отладки Django - это удобный инструмент для определения узкого места.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...