#python #django #django-rest-framework #base64
#python #django #django-rest-framework #base64
Вопрос:
Прежде всего, я довольно новичок в 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.
Ответ №1:
Хорошо, итак, мне удалось придумать (хакерский?) решение.
В serializers.py я помещаю свое поле base64 как 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)
И это возвращает полный путь к моему изображению!
Ответ №2:
Поскольку ваш метод 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 внутри @newest action и попытаться добавить его в ответ, но думаю, что вы можете создать только одну модель Advert с вашим полем изображения и одним сериализатором для него, где вы определите Base64ImageField.
Комментарии:
1. Спасибо, что нашли время ответить. Даже если я прокомментирую «новейший» кодовый блок, ничего не изменится при выполнении POST-запросов к моим объявлениям. Объявления регистрируются как обычно, а изображение по-прежнему возвращает null. Я понимаю, что это связано с возвратом объявления, которое не содержит поля изображения, однако я не знаю, как заставить его вернуть URL.