我在网上针对DRF上的这个问题进行了一些研究。当一个图像在后期DRF工作得很好。但是当一个帖子中有3或5个图像时,Django只保存POST查询中的第一个图像而其他图像不保存在数据库中。 问题是如何在一个帖子中正确处理多个图像上传。
Django版
Rest框架版
Python版
这是我的代码,我试图做的是:
class UserModel(AbstractEmailUser):
first_name = models.CharField(max_length=30, db_index=True)
last_name = models.CharField(max_length=50, db_index=True)
details = JSONField(null=True, blank=True, db_index=True)
avatar = models.ImageField(blank=True, null=True, upload_to='avatar')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.email)
class UserImages(models.Model):
image = models.ImageField(upload_to='images', db_index=True)
user = models.ForeignKey('UserModel',related_name='user')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.user)
在模型中,我有从User到UserImages的相关字段。出于POST邮件查询的目的,我手动添加用户ID以处理FK。
class SerializerUserImages(serializers.ModelSerializer):
class Meta:
model = UserImages
def create(self, validated_data):
imgs = UserImages.objects.create(**validated_data)
return imgs
也许在这里我必须做一些for循环来完成乘法图像的保存方法。
class UploadImages(APIView):
authentication_classes = (JSONWebTokenAuthentication,)
@parser_classes((FormParser, MultiPartParser, FileUploadParser))
def post(self, request, format=None):
serializer = SerializerUserImages(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(data={"msg": serializer.data}, status=status.HTTP_200_OK)
else:
return Response(data={"msg": serializer.errors}, status=status.HTTP_406_NOT_ACCEPTABLE)
包含所有解析器以处理此帖子查询。
这是 request.data = <QueryDict: {'image': [<InMemoryUploadedFile: top_20_cro.png (image/png)>, <InMemoryUploadedFile: images.jpg (image/jpeg)>], 'user': ['2', '2']}>
这是来自POSTMAN的请求POST的副本:
POST /api/images/ HTTP/1.1
Host: 127.0.0.1:8000
Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJvcmlnX2lhdCI6MTQ3MjIwMTcwMSwiZXhwIjoxNDcyMjMxNzAxLCJ1c2VyX2lkIjoyLCJlbWFpbCI6Im1hcmluLmJyZWthbG9AZ21haWwuY29tIiwidXNlcm5hbWUiOiJtYXJpbi5icmVrYWxvQGdtYWlsLmNvbSJ9.Fi3kmXJ44E_qhHHioniQ-cqri-u2ELU-XmpE_1oJ4Fk
Cache-Control: no-cache
Postman-Token: 1e53ac06-ed37-ff6e-2dc5-117976b86a5e
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="image"; filename=""
Content-Type:
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="user"
2
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="filename"
image
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="user"
2
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="filename"
image
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="image"; filename=""
Content-Type:
------WebKitFormBoundary7MA4YWxkTrZu0gW--
如果没有一些伟大的魔法,如何处理这个问题,是否有一些我错过的简单逻辑。
答案 0 :(得分:0)
尝试为图片设置文件名,我的意思是用filename=""
,filename="image-1"
等替换filename="image-2"
。文件应该有不同的文件名,或者它们互相覆盖。
答案 1 :(得分:0)
只需添加
many=True
使用序列化程序初始化程序。例如:
serializer = SerializerUserImages(data=request.data, many=True)
这应该可以解决问题。
另请查看ListSerializers
答案 2 :(得分:0)
好的,这是我对这个问题的一些逻辑,所以我希望有人会为此目的使用这个代码(hack):
class SerializerTest(serializers.Serializer):
image = serializers.ListField(child=serializers.ImageField(required=True))
def create(self, validated_data):
for attr, value in validated_data.items():
if attr == 'image':
for x in value:
c = UserImages.objects.create(image=x, user_id=UserModel.objects.get(id=self.context['request'].user.id).id)
c.save()
return validated_data
我已经为一个字段 img 更新了我的序列化器。并使用for循环从POST中提取图像。正如您所见,我调用查询将图像存储到FK用户的数据库中。这项工作非常好。
class UploadImages(APIView):
authentication_classes = (JSONWebTokenAuthentication,)
@parser_classes((FormParser, MultiPartParser, FileUploadParser))
def post(self, request, format=None):
serializer = SerializerTest(data=request.data, context={'request':request})
if serializer.is_valid():
serializer.save()
if len(serializer.data['image']) > 0:
que = UserImages.objects.filter(user=request.user.id)
ser = SerializerUserImages(que, many=True)
return Response(data={"msg": ser.data}, status=status.HTTP_200_OK)
else:
return Response(data={"msg": 'Provide images!'}, status=status.HTTP_406_NOT_ACCEPTABLE)
else:
return Response(data={"msg": serializer.errors}, status=status.HTTP_406_NOT_ACCEPTABLE)