Python Django 序列化程序 Imagefield 以获取完整 URL

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35522768/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 16:32:52  来源:igfitidea点击:

Django serializer Imagefield to get full URL

pythondjangodjango-rest-framework

提问by Khant Thu Linn

I am beginner to Django and currently, I can construct model like this.

我是 Django 的初学者,目前,我可以构建这样的模型。

enter image description here

在此处输入图片说明

models.py

模型.py

class Car(models.Model):
    name = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    photo = models.ImageField(upload_to='cars')

serializers.py

序列化程序.py

class CarSerializer(serializers.ModelSerializer):
    class Meta:
        model = Car
        fields = ('id','name','price', 'photo') 

views.py

视图.py

class CarView(APIView):
    permission_classes = ()
    def get(self, request):
        car = Car.objects.all()
        serializer = CarSerializer(car)
        return Response(serializer.data)

For photo, it doesn't show full URL. How can I show full URL?

对于照片,它不显示完整的 URL。如何显示完整的 URL?

采纳答案by blacklwhite

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)).

Django是不是提供了一个绝对URL存储在图像的models.ImageField(至少如果你不包括域名中MEDIA_URL,包括域名,不推荐,除非你正在主持一个不同的服务器上的媒体文件(例如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:

但是,您可以修改序列化程序以使用自定义serializers.SerializerMethodField. 在这种情况下,您的序列化程序需要进行如下更改:

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_URLparameters and that you can access a photo via your browser http://localhost:8000/path/to/your/image.jpg.

还要确保您已设置 DjangoMEDIA_ROOTMEDIA_URL参数,并且您可以通过浏览器访问照片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:

正如piling所指出的,您需要在views.py中初始化序列化程序时添加请求:

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

回答by Hakim

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

对于未来的访问者,如果视图方法已经返回序列化对象,则无需向序列化程序添加另一个字段。唯一需要的是添加上下文,因为它需要生成超链接,如drf 文档中所述

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

回答by Njeru Cyrus

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)

回答by Pooya Sagharchi

It's better to use this code, due to the above code doesn't check the image is null able or not.

最好使用此代码,因为上面的代码不会检查图像是否为空。

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')
            if photo and hasattr(photo, 'url'):
               photo_url = car.photo.url
               return request.build_absolute_uri(photo_url)
            else:
               return None

回答by abhishek kumar

serializers.py

序列化程序.py

 class BannerSerializer(serializers.ModelSerializer):
        image = serializers.SerializerMethodField()
        def get_image(self, obj):
            return self.context['request'].build_absolute_uri( obj.image.url)

views.py

视图.py

            banner = Banner.objects.all()
            banner_data = BannerSerializer(banner,many=True, context={'request': request})
            data = banner_data.data
            return Response({"data":data})

回答by Sailist

I read the implement of the Serializer, and find the simplest way is to extends ImageField:

我阅读了Serializer的实现,发现最简单的方法是扩展ImageField:

from django.db import models

class ImageField(models.ImageField):
    def value_to_string(self, obj): # obj is Model instance, in this case, obj is 'Class'
        return obj.fig.url # not return self.url

class Class(models.Model):
    name = models.CharField(max_length=50)
    intro = models.CharField(max_length=200)
    # fig = models.ImageField(upload_to="classes")
    fig = ImageField(upload_to="classes") 

    def __str__(self):
        return repr(self,"name")