URL возврата в POST-методе при работе с base64ImageField и вложенными сериализаторами - PullRequest
0 голосов
/ 18 апреля 2019

Прежде всего, я довольно новичок в Django и в равной степени новичок в бэкэнд-разработке, поэтому, пожалуйста, будьте осторожны со мной.

Я настраиваю серверную часть для мобильного приложения, в которой пользователь должен иметь возможность размещать рекламу с изображением, прикрепленным к нему через запросы Http. Прямо сейчас это работает так, как должно, пользователь отправляет запрос POST, содержащий всю необходимую информацию, и возвращает ответ, содержащий всю соответствующую информацию, за исключением изображения, которое null . Я знаю, что изображение успешно загружено на сервер, однако я не могу понять, как вернуть URL-адрес изображения обратно в ответ.

Вот мой код:

models.py

class Advert(models.Model):

    owner=models.ForeignKey(User, on_delete=models.CASCADE, related_name="adverts")
    book_title = models.CharField(max_length=250)
    price = models.PositiveSmallIntegerField()
    created_at = models.DateTimeField(default=now())

    def __str__(self):
        return self.book_title + ' - ' + self.contact_info


class AdvertImage(models.Model):
    advert = models.ForeignKey(Advert, on_delete=models.CASCADE, related_name="image", null=True)
    image = models.ImageField(upload_to = 'ad_images', null=True)

    def __str__(self):
        return self.image.name

Мой сериализатор выглядит следующим образом:

serializers.py

from rest_framework import serializers
from .models import Advert, AdvertImage
from drf_extra_fields.fields import Base64ImageField
from django.contrib.auth.models import User

class AdvertPostSerializer(serializers.ModelSerializer):
    image =  Base64ImageField(max_length=None, use_url=True, required=False)

    class Meta:
        model = Advert
        fields = (
        'id',
        'price',
        'book_title',
        'image')

    def create(self, validated_data):
        try:
            image_data = validated_data.pop('image')
        except:
            image_data = None
        advert = Advert.objects.create(**validated_data)
        if image_data is not None:
            image = AdvertImage.objects.create(advert=advert, image=image_data)

        return advert

И это мое мнение:

views.py

class AdvertViewSet(viewsets.ModelViewSet):
    queryset = Advert.objects.all()
    permission_classes = (AllowAny,)

    def get_serializer_class(self):
        if self.action == 'create':
            return AdvertPostSerializer
        return AdvertSerializer

    @action(methods=['get'], detail=False)
    def newest(self,request):
        newest = self.get_queryset().order_by('created_at').last()
        serializer = self.get_serializer_class()(newest)
        return Response(serializer.data)

    def perform_create(self, serializer):
        return serializer.save(owner=self.request.user)

Чтобы проиллюстрировать, что происходит, вот запрос POST:

POST http://localhost:8000/post-advert/ 
"Authorization: Token 980436128332ce3" 
book_title=my book 
price=1000
image=data:image/png;base64,iVBORHJvZmlsZSB0e//+egAAAAASUVORK5CYII=

А это ответ:

{
    "book_title": "my book",
    "id": 45,
    "image": null,
    "price": 1000,
}

Просмотр в базе данных и отправка второго GET-запроса в другое представление показывает, что все загружено, как должно, и внешние ключи и все такое работает, как они должны, просто мне действительно трудно понять, как отправить верните URL изображения в ответ на успешный POST.

Ответы [ 2 ]

0 голосов
/ 22 апреля 2019

Хорошо, так что мне удалось придумать (хакерское?) Решение.

В serializers.py я поставил свой Base64Field как read_only = True:

class AdvertPostSerializer(serializers.ModelSerializer):
    image =  Base64ImageField(max_length=None, use_url=True, required=False, read_only=True)
    ...

Затем в моем views.py для моего AdvertViewSet я переписал свой метод create () как таковой:

def create(self, request, format='json'):
        serializer = PostAdvertSerializer(data=request.data)
        if serializer.is_valid():
            advert = serializer.save()
            if advert:
                json = serializer.data
                advertImageURL = AdvertImage.objects.get(advert=advert).image.url
                json['img_link'] = request.build_absolute_uri(advertImageURL)
                return Response(json, status=status.HTTP_201_CREATED)

И это возвращает полный путь к моему изображению!

0 голосов
/ 18 апреля 2019

Поскольку ваш метод get_queryset () в

 newest = self.get_queryset().order_by('created_at').last()

возвращает Объявление объект модели:

class AdvertViewSet(viewsets.ModelViewSet):
    queryset = Advert.objects.all()

, у которого нет поля изображения.Затем вы создаете AdvertPostSerializer объект и инициализируете его с помощью новейшего набора запросов, который является набором запросов Advert модели без вашего изображения .

serializer = self.get_serializer_class()(newest)

Вы можете каким-то образом получить AdvertImage объект внутри @ новейшее действие и попытаться добавить его в ответ, но подумайте, что вы можете создать только одну модель Объявление с вашим полем image и одним сериализатором для него, где вы определите Base64ImageField .

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