Python 3.x 如何在Django Rest框架中使用base64上传多个文件?
我开始学习DRF,并尝试在VueJs上克隆Twitter来提高自己 在VueJs端,我使用FileReader进行文件上传,并在提交表单时将上传图像的base64代码发送到DRF。在DRF方面,我将这些base64代码转换为ContentFile,但最后我得到了下面提到的错误Python 3.x 如何在Django Rest框架中使用base64上传多个文件?,python-3.x,django,vue.js,django-rest-framework,Python 3.x,Django,Vue.js,Django Rest Framework,我开始学习DRF,并尝试在VueJs上克隆Twitter来提高自己 在VueJs端,我使用FileReader进行文件上传,并在提交表单时将上传图像的base64代码发送到DRF。在DRF方面,我将这些base64代码转换为ContentFile,但最后我得到了下面提到的错误 {'files': [{'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got ContentFile.'
{'files': [{'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got ContentFile.', code='invalid')]}, {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got ContentFile.', code='invalid')]}]}
Internal Server Error: /api/add-tweet/
Traceback (most recent call last):
File "C:\Users\adilc\Desktop\twitter-vue-django\twitter\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\adilc\Desktop\twitter-vue-django\twitter\lib\site-packages\django\core\handlers\base.py", line 204, in _get_response
response = response.render()
File "C:\Users\adilc\Desktop\twitter-vue-django\twitter\lib\site-packages\django\template\response.py", line 105, in render
self.content = self.rendered_content
File "C:\Users\adilc\Desktop\twitter-vue-django\twitter\lib\site-packages\rest_framework\response.py", line 70, in rendered_content
ret = renderer.render(self.data, accepted_media_type, context)
File "C:\Users\adilc\Desktop\twitter-vue-django\twitter\lib\site-packages\rest_framework\renderers.py", line 100, in render
ret = json.dumps(
File "C:\Users\adilc\Desktop\twitter-vue-django\twitter\lib\site-packages\rest_framework\utils\json.py", line 25, in dumps
return json.dumps(*args, **kwargs)
File "C:\Users\adilc\AppData\Local\Programs\Python\Python38\lib\json\__init__.py", line 234, in dumps
return cls(
File "C:\Users\adilc\AppData\Local\Programs\Python\Python38\lib\json\encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "C:\Users\adilc\AppData\Local\Programs\Python\Python38\lib\json\encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "C:\Users\adilc\Desktop\twitter-vue-django\twitter\lib\site-packages\rest_framework\utils\encoders.py", line 50, in default
return obj.decode()
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
如何在Rest框架上实现使用base64代码上传多个文件
views.py
class TweetCreateAPIView(APIView):
def post(self, request):
files = request.data.get('files')
if files:
files_list = []
for file in files:
file_data = file
form, filestr = file_data.split(';base64,')
ext = form.split('/')[-1]
data = ContentFile(base64.b64decode(filestr), name='temp.'+ext)
files_list.append(data)
request.data.update({'files': files_list})
serializer = TweetSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user=request.user)
print(serializer.errors)
return Response(
serializer.data,status=status.HTTP_201_CREATED
)
序列化程序.py
class FileSerializer(serializers.ModelSerializer):
file = serializers.FileField()
class Meta:
model = File
fields = ('file',)
class TweetSerializer(serializers.ModelSerializer):
likes = serializers.SerializerMethodField(read_only = True)
files = FileSerializer(many=True, required=False)
user = serializers.StringRelatedField(read_only=True)
class Meta:
model = Tweet
fields = [
'id',
'user',
'content',
'likes',
'files',
]
def get_likes(self, obj):
return obj.likes.count()
models.py
def upload_to(instance, filename):
username = instance.post.user.username
return '%s/%s/%s' %('TweetFiles', username, filename)
class CommonField(models.Model):
content = models.TextField(null=False, blank=False)
created_date = models.DateTimeField(auto_now_add = True)
class Meta:
abstract = True
ordering = ['-created_date']
class Like(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE,related_name = 'likes')
post = models.ForeignKey("Tweet",on_delete=models.CASCADE)
created_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.username +" Liked "+ str(self.post.id)
class Tweet(CommonField):
user = models.ForeignKey(User, related_name='tweets', on_delete=models.CASCADE, null=False, blank=False)
likes = models.ManyToManyField(User,related_name='tweet_user', blank=True, through=Like)
class Comment(CommonField):
user = models.ForeignKey(User, related_name='comments', on_delete=models.CASCADE, null=False, blank=False)
class File(models.Model):
post = models.ForeignKey(to=Tweet, on_delete=models.CASCADE,related_name='files')
file = models.FileField(upload_to=upload_to, null=True, blank=True)
TweetForm.vue(仅限数据和提交格式方法)
data(){
return {
tweet: '',
files: [],
}
},
methods: {
submitForm(){
const data = {
'content': this.tweet,
'files': this.files
}
axios.post('/api/add-tweet/', data)
.then((result) => {
console.log(result.data)
this.tweet = ''
this.files = []
this.$store.commit('removeFiles')
}).catch((err) => {
console.log(err)
});
},