Search code examples
pythondjangodjango-rest-frameworkimagefield

How can I get the full url of the image in DRF?


I am not good at English. I hope you understand.

  1. There can be multiple images in the diary.
  2. Diary and DiaryImage are in a 1:N relationship.

this is my model

from django.db import models

from userSystem.models import User


class Diary(models.Model):
    id = models.BigAutoField(primary_key=True)
    user = models.ForeignKey(User, related_name="diary_user", on_delete=models.CASCADE, null=True)
    title = models.CharField(max_length=30)
    content = models.CharField(max_length=800)
    date_created = models.DateField(auto_now_add=True)


class DiaryImage(models.Model):
    diary = models.ForeignKey(Diary, on_delete=models.CASCADE)
    image = models.ImageField(default='/media/diary/default_image.jpeg', upload_to='diary',
                              blank=True, null=True)

this is my serializer

from rest_framework import serializers

from diary.models import DiaryImage, Diary


class DiaryImageSerializer(serializers.ModelSerializer):
    image = serializers.ImageField(use_url=True)

    class Meta:
        model = DiaryImage
        fields = ['image']


class DiarySerializer(serializers.ModelSerializer):
    images = serializers.SerializerMethodField()

    def get_images(self, obj):
        image = obj.diaryimage_set.all()
        return DiaryImageSerializer(instance=image, many=True).data

    class Meta:
        model = Diary
        fields = ['id', 'title', 'content', 'date_created', 'images']

    def create(self, validated_data):
        instance = Diary.objects.create(**validated_data)
        image_set = self.context['request'].FILES
        for image_data in image_set.getlist('image'):
            DiaryImage.objects.create(diary=instance, image=image_data)
        return instance

this is my view

from diary.serializers import DiarySerializer


class DiaryViewSet(viewsets.ModelViewSet):
    permission_classes = [permissions.IsAuthenticated, ]
    serializer_class = DiarySerializer

    def get_queryset(self):
        return self.request.user.diary_user.all()

settings.py

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

urls.py

diary_list = DiaryViewSet.as_view({"get": "list", "post": "create"})


urlpatterns = [
    path('admin/', admin.site.urls),
    path('diary/', diary_list, name="diary-list"),

] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

When I ran this code, the image was saved successfully. However, when loading the saved image, the full url does not appear.

Like this,

{
    "id": 70,
    "title": "hello!",
    "content": "hello_content",
    "date_created": "2021-03-31",
    "images": [
        {
            "image": "/media/diary/DRF_Imagefield_1_xVENDCo.png"
        },
        {
            "image": "/media/diary/django_test_IGFIyYm.png"
        }
    ]
}

How can I get the full url of the image?


Solution

  • The FileField and ImageField automatically try to use the request from the context if it is passed to the serializer to build the absolute url. You should pass the context from your DiarySerializer to the DiaryImageSerializer:

    class DiarySerializer(serializers.ModelSerializer):
        images = serializers.SerializerMethodField()
    
        def get_images(self, obj):
            image = obj.diaryimage_set.all()
            return DiaryImageSerializer(instance=image, many=True, context=self.context).data
        
        # Rest of code