Django, REST framework - Как гарантировать, что абсолютный URL будет возвращен для изображения? - PullRequest
0 голосов
/ 28 марта 2020

Мне нужно, чтобы viewset всегда возвращал абсолютный URL для полей изображения avatar / avatar_thumbnail в ответ, но я получаю относительные пути. У меня есть два таких случая: 1-й) находится в поле изображения во вложенном сериализаторе, 2-й) в наборе, где я хочу использовать два сериализатора в методе получения.

models.py

class CustomUser(AbstractUser):
  avatar = ProcessedImageField(upload_to='users/',format='JPEG',options={'quality': 60})
  avatar_thumbnail = ImageSpecField(source='avatar',processors=[ResizeToFill(50, 50)],format='JPEG')

settings.py

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

urls.py

if settings.DEBUG:
    from django.conf.urls.static import static
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)here

forum / api / serializers.py (вложенный сериализатор)

class UserSerializer(serializers.ModelSerializer):
    avatar_thumbnail = serializers.ImageField(read_only=True)

    class Meta:
        model = CustomUser
        fields = ['id', 'username', 'avatar_thumbnail']

class ThreadSerializer(serializers.ModelSerializer):

    class Meta:
        model = Thread
        fields = ['id', 'title', 'subject', 'user']

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        representation['user'] = UserSerializer(instance.user).data
        return representation

forum / api / views.py

class ThreadViewSet(viewsets.ModelViewSet):
    serializer_class = ThreadSerializer
    queryset = Thread.objects.all()

Для UserViewSet у меня также есть похожая проблема с URL для "аватара". Мне нужны абсолютные URL. Я получаю относительный URL, но только когда перезаписываю метод извлечения в viewset. (Я перезаписываю его, чтобы использовать другой сериализатор «UserPrivateSerializer» для пользователя, который является владельцем профиля). Для списка я всегда получаю абсолютный URL.

users / api / serializers.py

class UserPublicSerializer(serializers.ModelSerializer):

class Meta:
    model = CustomUser
    fields = ['id', 'username', 'avatar']

class UserPrivateSerializer(serializers.ModelSerializer):    
    email = serializers.EmailField(required=True)

    class Meta:
        model = CustomUser
        fields = ['id', 'username', 'email', 'avatar']

users / api / views.py (Здесь проблема с дополнительным сериализатором, который я хочу использовать в методе получения)

class UserViewSet(viewsets.ModelViewSet):
    queryset = CustomUser.objects.exclude(username='user_deleted')
    serializer_class = UserPublicSerializer
permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]

def retrieve(self, request, *args, **kwargs):
    """Custom retrieve method use UserPrivateSerializer if the user object is requested by it's owner.
    """
    super().retrieve(request, *args, **kwargs)
    instance = self.get_object()
    if request.user == instance:
        serializer = UserPrivateSerializer(instance)
    else:
        serializer = UserPublicSerializer(instance)
    return Response(serializer.data, status=status.HTTP_200_OK)

1 Ответ

0 голосов
/ 28 марта 2020

Я обнаружил, что проблема решается, когда я добавляю контекст к сериализаторам.

forum / api / serializers.py

class ThreadSerializer(serializers.ModelSerializer):

    class Meta:
        model = Thread
        fields = ['id', 'title', 'subject', 'user']

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        representation['user'] = UserSerializer(instance.user, context=self.context).data
        return representation

users / api / views.py

class UserViewSet(viewsets.ModelViewSet):
    queryset = CustomUser.objects.exclude(username='user_deleted')
    serializer_class = UserPublicSerializer
    permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]

    def retrieve(self, request, *args, **kwargs):
        super().retrieve(request, *args, **kwargs)
        instance = self.get_object()
        if request.user == instance:
            serializer = UserPrivateSerializer(instance, context={'request': request})
        else:
            serializer = UserPublicSerializer(instance, context={'request': request})
        return Response(serializer.data, status=status.HTTP_200_OK)

Я нашел свой ответ здесь: Django REST Framework и абсолютный URL-адрес FileField "Запрос должен быть доступен для сериализатора, чтобы он мог создать полный абсолютный URL-адрес для вы. Один из способов - явно передать его при создании сериализатора "

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...