即使在创建帖子期间使用 Postman 将文件上传到该字段后,Django Rest Framework 仍显示字段错误

Posted

技术标签:

【中文标题】即使在创建帖子期间使用 Postman 将文件上传到该字段后,Django Rest Framework 仍显示字段错误【英文标题】:Django Rest Framework showing a field error even after uploading the file to that field with Postman during creating the post 【发布时间】:2020-11-16 13:02:27 【问题描述】:

我是 DRF 的新手,我有这个序列化程序,但我无法创建帖子,因为即使在将图像上传到该字段后,它仍然在邮递员中向我显示这个。在普通的 django 中,这个 PostImage 模型与 Post 有一个外键关系,我使用一个表单集来上传多个图像。


"postimage": [
    "This field is required."
    ]

有人可以帮我解决这个问题并告诉我它是如何工作的吗?

serializer.py

class PostImageSerializer(serializers.ModelSerializer):
   class Meta:
       model = PostImage
       fields = ['id','post', 'images',]  

class PostCreateSerializer(serializers.ModelSerializer):
    postimage = PostImageSerializer(many=True)
    class Meta:
        model = Post
        fields = ['id','title', 'image', 'postimage',]

views.py

def create_post_api_view(request):
    user = request.user
    post = Post(user=user)
    serializer = PostCreateSerializer(post, data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

更新:

有效载荷。

Authorization: Token XXXX

: 
User-Agent: PostmanRuntime/7.26.2
Accept: */*
Postman-Token: 066c9a26-af76-4a44-9e9f-a3326050fa"
Host: 127.0.0.1:8000
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: multipart/form-data; boundary=--------------------------554448102853056787089432
Content-Length: 123293

Request Body
title: "Another Trial api posts"
image: …
_events: 
_eventsCount: 3
_readableState: …
autoDestroy: false
awaitDrain: 0
buffer: …
head: null
length: 0
tail: null
decoder: null
defaultEncoding: "utf8"
destroyed: true
emitClose: false
emittedReadable: false
encoding: null
endEmitted: true
ended: true
flowing: true
highWaterMark: 65536
length: 0
needReadable: false
objectMode: false
paused: false
pipes: null
pipesCount: 0
readableListening: false
reading: false
readingMore: false
resumeScheduled: false
sync: false
autoClose: true
bytesRead: 5473
closed: true
fd: null
flags: "r"
mode: 438
path: "C:\Users\danny\Desktop\test images\cat.jpg"
readable: false

postimage: [2]
0: …
_events: 
_eventsCount: 3
_readableState: …
autoDestroy: false
awaitDrain: 0
buffer: …
decoder: null
defaultEncoding: "utf8"
destroyed: true
emitClose: false
emittedReadable: false
encoding: null
endEmitted: true
ended: true
flowing: true
highWaterMark: 65536
length: 0
needReadable: false
objectMode: false
paused: false
pipes: null
pipesCount: 0
readableListening: false
reading: false
readingMore: false
resumeScheduled: false
sync: false
autoClose: true
bytesRead: 7350
closed: true
fd: null
flags: "r"
mode: 438
path: "C:\Users\danny\Desktop\test images\041520_mt_supernova_feat-1028x579.jpg"
readable: false
1: …
_events: 
_eventsCount: 3
_readableState: …
autoDestroy: false
awaitDrain: 0
buffer: …
decoder: null
defaultEncoding: "utf8"
destroyed: true
emitClose: false
emittedReadable: false
encoding: null
endEmitted: true
ended: true
flowing: true
highWaterMark: 65536
length: 0
needReadable: false
objectMode: false
paused: false
pipes: null
pipesCount: 0
readableListening: false
reading: false
readingMore: false
resumeScheduled: false
sync: false
autoClose: true
bytesRead: 109530
closed: true
fd: null
flags: "r"
mode: 438
path: "C:\Users\danny\Desktop\test images\Tischvase-X-Form-VX-silber-dek-Holst-Porzellan.jpg"
readable: false
Response Headers
Date: Mon, 27 Jul 2020 10:09:18 GMT
Server: WSGIServer/0.2 CPython/3.8.2
Content-Type: application/json
Vary: Accept, Accept-Language, Cookie
Allow: POST, OPTIONS
X-Frame-Options: SAMEORIGIN
Content-Length: 41
Content-Language: en

Response Body
"postimage":["This field is required."]

更新的创建序列化器

class PostCreateSerializer(serializers.ModelSerializer):
images = serializers.ImageField()
class Meta:
    model = Post
    fields = ['id','title','image', 'images',]

def create(self,validated_data):
    user = self.context['request'].user
    title = validated_data['title']
    image = self.context['request'].FILES.get('image')
    images = self.context['request'].FILES.get('images')
    m1 = Post(
        title=title,
        image=image,
        user=user
    )
    m1.save()
    m2 = PostImage(
        post=m1,
        images=images
    )
    m2.save()
    validated_data['images']=m2.images
    return validated_data

基于上次编辑的响应


"title": "Another Trial api posts",
"image": null,
"images": "http://127.0.0.1:8000/media/posts/postimage/Tischvase-X-Form-VX-silber-dek-Holst-Porzellan.jpg"

现在另一张图片为空..

谢谢

【问题讨论】:

那么邮递员创建的有效载荷是什么? 邮递员显示的是json输出吗? 是的,请缩短任何过长的文本数据(如 base64 编码的图像数据,如果你真的在上传图像,你会拥有)。 好的。谢谢..我猜输出邮递员正在显示,我已经在问题中找到了,第一部分带有“postimage”。它还显示状态错误 HTTP 400 bad request。 不,这是响应。有效负载是请求。见***.com/a/47278422 【参考方案1】:

我认为您应该为您的序列化程序编写自己的创建方法。像这样的

型号

class MyModel(models.Model):
    field1 = models.CharField(max_length=50)
    def __str__(self):
        return str(self.field1)

class MyModel2(models.Model):
    field2 = models.CharField(max_length=50)
    image = models.ImageField(upload_to='images')
    foreignkeytomymodel = models.ForeignKey(MyModel,on_delete=models.CASCADE)

    def __str__(self):
        return str(self.field2)

序列化器

class MyModelSerializer(serializers.ModelSerializer):
    field2 = serializers.CharField(required=True)
    image = serializers.ImageField(required=True)
    class Meta:
        model = MyModel
        fields = ['field1','field2', 'image']

    def create(self,validated_data):
        field1 = validated_data['field1']
        field2 = validated_data['field2']
        image = self.context['request'].FILES.get('image')
        m1 = MyModel(
            field1=field1
        )
        m1.save()
        m2 = MyModel2(
            field2=field2,
            image=image,
            foreignkeytomymodel=m1
        )
        m2.save()
        validated_data['field2']=m2.field2
        validated_data['image']=m2.image
        return validated_data

观看次数

serializer = MyModelSerializer(data=request.data, context='request':request)
if serializer.is_valid():
    serializer.save()
    return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)

根据您的序列化程序更新 -

class PostCreateSerializer(serializers.ModelSerializer):
    images = serializers.ImageField()
    class Meta:
        model = Post
        fields = ['id','title','image', 'images',]

    def create(self,validated_data):
        user = self.context['request'].user
        title = validated_data['title']
        image = self.context['request'].FILES.get('image')
        images = self.context['request'].FILES.get('images')
        m1 = Post(
            title=title,
            image=image,
            user=user
        )
        m1.save()
        m2 = PostImage(
            post=m1,
            images=images
        )
        m2.save()
        validated_data['image']=m1.image
        validated_data['images']=m2.images
        return validated_data

【讨论】:

感谢您的回复。在这种情况下,这应该用于 PostSerializer 吗?你能告诉我 MyModel12 是什么吗? 谢谢..让我试试这个方法! 您好,我试过了,现在问题是只有 1 个模型数据正在保存,另一个显示为空 发布模型..我在没有用户的情况下尝试过,但它显示了 user_id not null 约束错误或其他东西。 请同时添加此行validated_data['image']=m1.image

以上是关于即使在创建帖子期间使用 Postman 将文件上传到该字段后,Django Rest Framework 仍显示字段错误的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 POSTMAN 应用程序将文件上传到 Amazon S3

通过使用 AWS-SDK PHP 生成的预签名帖子拒绝 AWS S3 上传访问

通过使用 AWS-SDK PHP 生成的预签名帖子拒绝 AWS S3 上传访问

在 POSTMAN 上使用 PUT/POST 方法上传文件

WordPress 将媒体上传到帖子问题

使用 Postman 上传 ASP Core WebApi 测试文件