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

#python #django #django-models #django-rest-framework #django-views

Вопрос:

Допустим, у меня есть простая модель 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 действие a для получения всех учетных записей, а также a Serializer для сериализации каждого элемента. JSON Возвращаемый объект имеет следующую форму:

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

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

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

Комментарии:

1. Наборы представлений используют сериализаторы, поэтому имеет смысл использовать набор представлений, чтобы получить то, что нужно сериализатору, и передать его ИМО

2. @BrianDestura Я вижу, так что вы хотите сказать, что ViewSet должен сделать этот REST вызов, и он передаст список этих элементов в Serializer , чтобы он мог правильно установить это поле для каждого элемента, который он сериализует?

3. Да! Результат вызова rest может быть передан в контекст сериализатора

Ответ №1:

Вы можете использовать декоратор действий в наборе представлений учетных записей для извлечения данных, в которых вы можете передавать идентификаторы учетных записей в URL-адресах.

 @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: учетные записи/цвет избранного/?идентификаторы учетных записей=1,2,3