web-dev-qa-db-fra.com

Django serializer Imagefield pour obtenir l'URL complète

Je suis débutant à Django et actuellement, je peux construire un modèle comme celui-ci.

enter image description here

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

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

views.py

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

Pour la photo, elle n'affiche pas l'URL complète. Comment afficher l'URL complète?

26
Khant Thu Linn

Django ne fournit pas d'URL absolue à l'image stockée dans un models.ImageField (au moins si vous n'incluez pas le nom de domaine dans le MEDIA_URL ; il n'est pas recommandé d'inclure le domaine, sauf si vous hébergez vos fichiers multimédias sur un autre serveur (par exemple, aws)).

Cependant, vous pouvez modifier votre sérialiseur pour renvoyer l'URL absolue de votre photo en utilisant un personnalisé serializers.SerializerMethodField . Dans ce cas, votre sérialiseur doit être modifié comme suit:

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)

Assurez-vous également que vous avez défini Django MEDIA_ROOTet MEDIA_URL paramètres et que vous pouvez accéder à une photo via votre navigateur http://localhost:8000/path/to/your/image.jpg.

Comme l'a souligné l'empilement, vous devez ajouter la demande lors de l'initialisation du sérialiseur dans vos vues.py:

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

Pour les futurs visiteurs, il n'est pas nécessaire d'ajouter un autre champ au sérialiseur si la méthode view renvoie déjà un objet sérialisé. La seule chose requise est d'ajouter le contexte car il est nécessaire de générer des hyperliens, comme indiqué dans la documentation drf

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

Classe de sérialiseur

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

Vue

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)
9
Njeru Cyrus

Il est préférable d'utiliser ce code, car le code ci-dessus ne vérifie pas que l'image est nulle ou non.

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
2
Pooya Sagharchi