Django - Получить урлы всех изображений, ссылающихся на пост?

У меня есть модель, в которой пост может содержать много фотографий. Я пытаюсь получить все посты, включая ImageField атрибут url (согласно документации Django FileField и ImageField имеют атрибут url). Поэтому я хотел бы в идеале вернуть все url-адреса изображений, связанных с постом (в идеале в порядке создания).

model.py

class Post(AbstractBaseModel):
    creator_id = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name="post_creator_id")
    goal_id = models.ForeignKey(Goal, on_delete=models.CASCADE)
    body = models.CharField(max_length=511, validators=[MinLengthValidator(5)])
    hash_tags = models.ManyToManyField(HashTag)


class Photo(AbstractBaseModel):
    created = models.DateTimeField('Created at', auto_now_add=True)
    post_id = models.ForeignKey(Post, on_delete=models.CASCADE)
    image = models.ImageField(upload_to=directory_path)

view.py

def get(self, request):
    data = Post.objects.order_by('created').values('body', 'goal_id__description', 'created',
                                                   'creator_id__username', replies=Count('replypost'),
                                                   cheers=Count('cheerpost'), image_urls='photo__image_url')
    return Response(list(data), status=status.HTTP_200_OK)

Пожалуйста, не используйте .values(…) [Django-doc] для выполнения сериализации JSON. Это уничтожит логический слой модели, а для связанных объектов будет действовать как множитель: на каждый связанный Photo будет повторяться body и т.д.

Мы можем определить функцию для получения URL изображения Photo с помощью:

class Photo(AbstractBaseModel):
    created = models.DateTimeField('Created at', auto_now_add=True)
    post_id = models.ForeignKey(Post, on_delete=models.CASCADE)
    image = models.ImageField(upload_to=directory_path)

    @property
    def image_url(self):
        return self.image.url

Вы можете работать с сериализаторами, которые определяют, как возвращать объекты. Для Photo мы можем работать с PhotoSerializer:

class PostSerialiser(serializers.ModelSerializer):
    image_urls = serializers.SlugRelatedField(
        source='photo_set', many=True, read_only=True, slug_field='image_url'
    )
    creator_name = serializers.SlugField()
    replies = serializers.IntegerField()
    cheers = serializers.IntegerField()
    goal_description = serializers.SlugField()

    class Meta:
        model = Post
        fields = ('body', 'goal_id', 'created', 'creator_name', 'goal_description', 'replies', 'cheers', 'created')

Затем мы можем сериализовать и вернуть соответствующие сериализованные данные с помощью:

from django.db.models import F, Count, Prefetch

def get(self, request):
    items = Post.objects.order_by('created').annotate(
        creator_name = F('creator_id__username'),
        goal_description = F('goal_id__description'),
        replies=Count('replypost', distinct=True),
        cheers=Count('cheerpost', distinct=True),
    ).prefetch_related(
        Prefetch('photo_set', Photo.objects.order_by('created'))
    )
    serializer = PostSerialiser(items, many=True)
    return Response({'data': serializer.data}, status=status.HTTP_200_OK)
Вернуться на верх