Django serializer Imagefield to get full URL

Solution 1:

Django is not providing an absolute URL to the image stored in a models.ImageField (at least if you don't include the domain name in the MEDIA_URL; including the domain is not recommended, except of you are hosting your media files on a different server (e.g. aws)).

However, you can modify your serializer to return the absolute URL of your photo by using a custom serializers.SerializerMethodField. In this case, your serializer needs to be changed as follows:

class CarSerializer(serializers.ModelSerializer):
    photo_url = serializers.SerializerMethodField()

    class Meta:
        model = Car
        fields = ('id','name','price', 'photo_url') 

    def get_photo_url(self, car):
        request = self.context.get('request')
        photo_url = car.photo.url
        return request.build_absolute_uri(photo_url)

Also make sure that you have set Django's MEDIA_ROOTand MEDIA_URL parameters and that you can access a photo via your browser http://localhost:8000/path/to/your/image.jpg.

As piling pointed out, you need to add the request while initialising the serializer in your views.py:

def my_view(request):
    …
    car_serializer = CarSerializer(car, context={"request": request})
    car_serializer.data

Solution 2:

For future visitors, there is no need to add another field to the serializer if the view method already returns a serialized object. The only thing required is to add the context since it is needed to generate hyperlinks, as stated in the drf documentation

@list_route()
def my_view(self, request):
    qs = Object.objects.all()
    return Response(MySerializer(qs, many=True, context={'request': request}).data)

Solution 3:

Serializer class

class CarSerializer(serializers.ModelSerializer):

  photo_url = serializers.ImageField(max_length=None, use_url=True, allow_null=True, required=False)
  class Meta:
      model = Car
      fields = ('id','name','price', 'photo_url')

View

class CarView(APIView):

    def get(self, request, *args, **kwargs):

        queryset = Car.objects.all()

        serializer = CarSerializer(queryset, many=True, context={"request":request})

        return Response(serializer.data, status=status.HTTP_200_OK)