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)