我有一个Vue前端,它从用户那里收集数据(和文件),并使用Axios将其发布到Django Rest框架端点。
下面是该函数的代码:
import { ref } from "vue";
import axios from "axios";
const fields = ref({
audience: "",
cancomment: "",
category: "",
body: "",
errors: [],
previews: [],
images: [],
video: [],
user: user,
});
function submitPost() {
const formData = {
'category': fields.value.category.index,
'body': fields.value.body,
'can_view': fields.value.audience,
'can_comment': fields.value.cancomment,
'video': fields.value.video,
'uploaded_images': fields.value.images,
'user': store.userId
};
console.log(formData['uploaded_images'])
axios
.post('api/v1/posts/create/', formData, {
headers: {
"Content-Type": "multipart/form-data",
"X-CSRFToken": "{{csrf-token}}"
}
})
.then((response) => {
if(response.status == 201){
store.messages.push("Post created successfully")
}
})
.catch((error) => {
messages.value.items.push(error.message)
})
}
当我发布数据时,我在服务器端看到的响应是:
uploaded_data = validated_data.pop('uploaded_images')
KeyError: 'uploaded_images'
来自这个序列化程式:
class PostImageSerializer(serializers.ModelSerializer):
class Meta:
model = PostImage
fields = ['image', 'post']
class PostSerializer(serializers.ModelSerializer):
images = PostImageSerializer(many=True, read_only=True, required=False)
uploaded_images = serializers.ListField(required=False, child=serializers.FileField(max_length=1000000, allow_empty_file=False, use_url=False),write_only=True)
class Meta:
model = Post
fields = [
"category",
"body",
"images",
"uploaded_images",
"video",
"can_view",
"can_comment",
"user",
"published",
"pinned",
"created_at",
"updated_at",
]
def create(self, validated_data):
uploaded_data = validated_data.pop('uploaded_images')
new_post = Post.objects.create(**validated_data)
try:
for uploaded_item in uploaded_data:
PostImage.objects.create(post = new_post, images = uploaded_item)
except:
PostImage.objects.create(post=new_post)
return new_post
尝试理解这一点,那么我的想法是正确的吗?DRF在数据发送到端点时保存序列化程序?我假设变量validated_data是request.data对象?那么为什么我会得到KeyError?我如何才能看到正在验证的数据是什么?或者在服务器端的post请求中发送。在浏览器中post请求中发送的数据如下所示:
-----------------------------2091287168172869498837072731
Content-Disposition: form-data; name="body"
Post
-----------------------------2091287168172869498837072731
Content-Disposition: form-data; name="can_view"
Everybody
-----------------------------2091287168172869498837072731
Content-Disposition: form-data; name="can_comment"
Everybody
-----------------------------2091287168172869498837072731
Content-Disposition: form-data; name="uploaded_images.0"; filename="tumblr_42e2ad7e187aaa1b4c6f4f7e698d03f2_c9a2b230_640.jpg"
Content-Type: image/jpeg
-----------------------------2091287168172869498837072731
Content-Disposition: form-data; name="body"
Post
-----------------------------2091287168172869498837072731
Content-Disposition: form-data; name="can_view"
Everybody
-----------------------------2091287168172869498837072731
Content-Disposition: form-data; name="can_comment"
Everybody
-----------------------------2091287168172869498837072731
Content-Disposition: form-data; name="uploaded_images.0"; filename="tumblr_42e2ad7e187aaa1b4c6f4f7e698d03f2_c9a2b230_640.jpg"
Content-Type: image/jpeg
(¼T¼Þ7ó[®«ý;>7гô
eIqegy[XbkéÉc¤ÎSFÌÔÂåÄAR§*P!I<R,4AP9ÖgÅÖYÔ×éu«ÅÉ<IJª+`,.uòÜtK7xéu.Ô¬]{ù£æÍ÷·n²±×:îã¡`UÐKxªyjxñDUAP¢+ÄÅB1yõçùuS5å
D÷ zö4®n¦Öod&<z¼P
W9©xeúD5ÈMpÖö¬ðÓKÊľO«oµÊMçÇy|z=^<AKêôz¼x##:ù;«OdÞ¢¶WRùººRêÜêú8ø¡ãÄ"¼AãÅj¿3ÆõÙRÆ]_MTÆ^;;
`ttR}mì¤*bêwy¾=d<xòøòxÄ(
以下是位于端点的ViewSet:
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
filter_backends = [django_filters.rest_framework.DjangoFilterBackend, filters.SearchFilter, django_filters.rest_framework.OrderingFilter]
# filterset_class = PostFilter
ordering_fields = ['created_at',]
search_fields = ['category', 'body']
permission_classes = [permissions.IsAuthenticated]
def get_serializer_context(self):
return {'request': self.request}
parser_classes = [MultiPartParser, FormParser]
lookup_field = 'slug'
1条答案
按热度按时间djmepvbi1#
因此,经过几个小时的研究,我找到了自己的解决方案。用于读取多个文件的方法就是从这个answer中获得的。通过将[对象FileList]分解为单独的文件并将它们附加到FormData中。模型就是基于这个answer
在后端,重写序列化程序的create方法,并循环访问resquest.POST.data,排除不需要的键,以访问文件。并将它们保存到Images模型中**(应命名为PostImage)**。
注意,我不访问文件的validated_data,而是直接从请求中检索它们。
我在前端使用了bootstrap5。
编辑:仅测试了两种类型的请求GET(列表)和POST(创建)(如您在vue组件中所见)
models.py:
serializers.py:
views.py:
TestComponent.vue: