Эффективная сериализация нескольких объектов, которым необходимо совершить REST-вызов

Допустим, у меня есть простая модель, Account, следующего вида:

    class Account(models.Model):
        name = models.CharField(db_index=True)

И AccountSerializer следующим образом:

    class AccountSerializer(serializers.ModelSerializer):
        name = CharField(source="account.name")
        def _get_favorite_color(self, obj: Account):
            # Make a rest call to get this account's favorite color
            favorite_color = _get_favorite_color(name)

У меня также есть ViewSet с действием list для получения всех счетов, а также Serializer для сериализации каждого элемента. Возвращаемый JSON имеет следующую форму:

{
    'accounts':[
        {'name':'dave', 'favorite_color':'blue'},
        {'name':'john', 'favorite_color':'black'},
    ]
}

Каким образом django-esque можно "массово" получить эти любимые цвета? Этот вызов REST для получения любимых цветов может принимать на вход список всех учетных записей id и возвращать их в одном списке, избегая n вызовов REST, когда достаточно одного.

Где эта логика будет иметь наибольший смысл? Я не могу поместить эту логику в Serializer, учитывая, что она обрабатывает только один объект за раз. Есть ли другое место, куда ее можно поместить, а не в ViewSet? Насколько я понимаю, ViewSet должны быть как можно более компактными.

Вы можете использовать декоратор действия в Account Viewset для получения данных, где вы можете передать идентификаторы счетов в url args.

@action(methods=['GET'], detail=False, url_name='favourite_color')
    def favourite_color(self, request, pk=None):
        account_ids = list(request.query_params.get('account_ids').split(","))
        queryset = Account.objects.filter(id__in=account_ids).values('favourite_color')
        # Not sure how favourite color is linked to account
        # You will get the values hitting one query, and you can make a json response which needs to be returned

        return Response(json_response_of_favourite_colors)
    

Url будет выглядеть примерно так:

url: accounts/favourite_color/?account_ids=1,2,3

Вернуться на верх