DRF, как я могу вернуть в представление только первый сериализованный объект?

в DRF есть ли способ получить одно вложенное изображение для отображения в представлении. В моем примере вы можете видеть, что в списке 2 фотографии. Что было бы лучшим решением для извлечения и отображения только этой первой фотографии? Это представление будет для списка домов, и я не хочу, чтобы отображалась каждая фотография, так как некоторые пользователи могут загружать более 30 фотографий.

            "url": "http://127.0.0.1:8000/api/v1/listings/1/",
            "address": "8753 sherwood dr apt 111",
            "image_set": [
                {
                    "photo": "http://127.0.0.1:8000/media/listing_images/front-view.png"
                },
                {
                    "photo": "http://127.0.0.1:8000/media/listing_images/image34453.png
                }
            ]
        },


class ImageSerializerForListingDetail(serializers.ModelSerializer):
    photo = serializers.ImageField(use_url=True, allow_empty_file=True)
    class Meta:
        model = Image
        fields = ('photo', )
    def get_image_url(self, listing):
        return listing.photo.url


class ListingListSerializer(serializers.HyperlinkedModelSerializer):
    photo = ImageSerializerForListingDetail(many=True, required=False)
    class Meta:
        model = Listing
        fields = ('url', 'address', 'photo', )


class ListingViewSet(viewsets.ModelViewSet):
    queryset = Listing.objects.all().order_by('id')
    permission_classes = [IsOwnerOrReadOnly, ]
    serializer_classes = {
        'list': ListingListSerializer,
        'retrieve': ListingSerializer
    }
    default_serializer_class = ListingSerializer

    def get_serializer_class(self):
        return self.serializer_classes.get(self.action, self.default_serializer_class)

    def create(self, request, *args, **kwargs):
        serializer = ListingSerializer(data=request.data, files=request.FILES)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

текущий код, который я только что попробовал, возвращает пустой список фотографий.... #

class ImageSerializerForListingDetail(serializers.ModelSerializer):
    photo = serializers.ImageField(allow_empty_file=True)

    class Meta:
        model = Image
        fields = ('photo', )

    def get_image_url(self, listing):
        return listing.photo.url



class ListingListSerializer(serializers.HyperlinkedModelSerializer):
    first_image = ImageSerializerForListingDetail(many=True, required=False)

    class Meta:
        model = Listing
        fields = ('url', 'address', 'first_image', )

    def get_first_image(self, obj):
        first_image = Image.objects.filter(listing=obj).first()
        first_image_serializer = ImageSerializerForListingDetail(first_image)
        return first_image_serializer.data

person master_j02    schedule 04.03.2020    source источник


Ответы (2)


Вы можете передать только первый элемент в свой сериализатор:

def get_queryset(self):
    return  Listing.objects.all().order_by('id').first() if self.action == 'retrieve' else Listing.objects.all().order_by('id')
person kamilyrb    schedule 04.03.2020
comment
Как я могу получить изображения в этом списке? Какая-то дополнительная фильтрация - это то, что я пытаюсь? Поскольку у изображений есть внешний ключ к листингу. - person master_j02; 04.03.2020
comment
это моя модель изображения class Image(models.Model): photo = models.ImageField(blank=True, upload_to=get_image_filename) listing = models.ForeignKey(Listing, on_delete=models.CASCADE) - person master_j02; 04.03.2020
comment
Я не понял, что ты хочешь. Можете ли вы объяснить более подробно? - person kamilyrb; 04.03.2020
comment
Моя цель - просто загрузить первое изображение. Я имею дело только с двумя моделями. Модель листинга и модель изображения. Модель изображения имеет два поля: фото и список. Какой листинг является внешним ключом к модели листинга. Я обновил сообщение с последним кодом, который я пытался. Теперь он возвращает пустой запрос. - person master_j02; 04.03.2020

Поскольку я не совсем уверен, как выглядит ваша модель и какую первую фотографию вы хотели бы представить (например, последняя загруженная, первая загруженная, последний идентификатор). Я буду использовать общий пример, чтобы объяснить решение.

Попробуйте serializers.SerializerMethodField() настроить поле, которое вы хотите представить последним.

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

Вот пример:

class UserSerializer(serializers.ModelSerializer):
    latest_group_id = serializers.SerializerMethodField()

    def get_latest_group_id(self, obj):
        return Group.objects.filter(user=obj).latest('id').id

Поскольку вы хотите указать URL-адрес фотографии, а не идентификатор, вот псевдокод.

class UserProfileSerializer(serializers.ModelSerializer):
    latest_image = serializers.SerializerMethodField()

    def get_latest_image(self, obj):
        latest_image = Image.objects.filter(user=obj).latest('id')
        latest_image_serializer = ImageSerializerForListingDetail(latest_image)
        # Deal with edge cases, e.g. latest_image_serializer is not valid
        return latest_image_serializer.data
person Jun Zhou    schedule 04.03.2020
comment
Моя цель - просто загрузить первое изображение. Я имею дело только с двумя моделями. Модель Listing и модель Image. Модель изображения имеет два поля: фото и список. Какой листинг является внешним ключом к модели листинга. Сейчас я играю с вашим кодом, пытаясь найти правильное решение. - person master_j02; 04.03.2020
comment
Из последнего кода, который вы разместили в своем вопросе, поле first_image в ListingListSerializer должно быть first_image = serializers.SerializerMethodField() - person Jun Zhou; 04.03.2020
comment
только что исправил это, лол. Все еще получаю пустой набор запросов, где должно быть мое поле first_image.. { "url": "http://127.0.0.1:8000/api/v1/listings/2/", "address": "4848 north florida dr" } - person master_j02; 04.03.2020
comment
Есть ли изображения, относящиеся к вашему списку (id=2)? - person Jun Zhou; 04.03.2020
comment
да, когда я действительно нажимаю на этот URL-адрес и перехожу к подробному просмотру, есть две фотографии, связанные с этим списком. - person master_j02; 04.03.2020
comment
Было бы полезно, если бы вы установили некоторые точки останова в функции get_latest_image, чтобы проверить, возвращается ли экземпляр изображения или нет. Кроме того, вы можете проверить данные сериализатора. - person Jun Zhou; 04.03.2020
comment
Давайте продолжим обсуждение в чате. - person Jun Zhou; 05.03.2020