首先,我是Django的新手,对于后端开发同样是新手,所以请放轻松。
我正在为移动应用程序设置一个后端,在该后端中,用户应该能够通过Http Request发布带有附加图像的广告。现在,它的工作方式应该像它应该的那样,用户发送一个包含所有必需信息的POST请求,并返回一个包含所有相关信息的响应,但图像为 null 除外。我知道图像已成功上传到服务器,但是我不知道如何将图像的URL返回到响应中。
以下是我的代码:
models.py
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE repub SYSTEM "C:\repub\Repub_V1.dtd">
<?xml-stylesheet href="C:\repub\repub.xsl" type="text/xsl"?>
<repub>
<head>
<title>xxx</title>
</head>
<body>
<sec>
<title>First Title</title>
<break name="1-1"/>
<pps>This is Sparta</pps>
<h1><page num="1"/>First Heading</h1>
<bl>This is another text</bl>
<fig><img src="images/img_1-1.jpg" alt=""/><fc>This is a caption</fc></fig>
<p>This is a sentence<br><p/></br> that will be broken down <br><p/></br>into separate paragraph tags.</p>
</break>
</sec>
</body>
</repub>
我的序列化器如下:
serializers.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
这是我的观点:
views.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
为说明会发生什么,这是一个POST请求:
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 http://localhost:8000/post-advert/
"Authorization: Token 980436128332ce3"
book_title=my book
price=1000
image=data:image/png;base64,iVBORHJvZmlsZSB0e//+egAAAAASUVORK5CYII=
查看数据库并将第二个GET请求发送到另一个视图表明,所有内容均按应有的方式上载,外键和其他功能均应按应有的方式工作,只是我很难弄清楚如何发送返回图片的URL作为对成功POST的响应。
答案 0 :(得分:0)
因为您的
中的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 。
答案 1 :(得分:0)
好的,所以我设法提出了一个(hacky?)解决方案。
在serializers.py中,我将Base64Field设置为read_only = True:
class AdvertPostSerializer(serializers.ModelSerializer):
image = Base64ImageField(max_length=None, use_url=True, required=False, read_only=True)
...
然后,在我的AdvertViewSet的views.py中,我这样覆盖了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)
这将返回我图像的完整路径!