Django REST Framework 업로드 이미지: "제출된 데이터가 파일이 아닙니다."
저는 Django에서 파일을 업로드하는 방법을 고민하고 있는데, 여기서 다음과 같은 오류로 인해 중대한 문제가 발생했습니다.
제출된 데이터는 파일이 아닙니다.폼의 부호화 타입을 확인합니다.
자세한 내용은 다음과 같습니다.
주의: Django Rest Framework Image Field도 살펴보고
serializer = ImageSerializer(data=request.data, files=request.FILES)
하지만 나는 이해한다
유형 오류:
__init__()
예기치 않은 키워드 인수 'files'를 받았습니다.
나는 가지고 있다Image
Django REST 프레임워크를 통해 소통하고 싶은 모델:
models.py
class Image(models.Model):
image = models.ImageField(upload_to='item_images')
owner = models.ForeignKey(
User, related_name='uploaded_item_images',
blank=False,
)
time_created = models.DateTimeField(auto_now_add=True)
serializers.py
class ImageSerializer(serializers.ModelSerializer):
image = serializers.ImageField(
max_length=None, use_url=True,
)
class Meta:
model = Image
fields = ("id", 'image', 'owner', 'time_created', )
설정을 지정합니다.화이
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
),
프론트 엔드(Angular 사용)JS 및angular-restmod
또는$resource
)의 송신JSON
로의 데이터.owner
그리고.image
폼의 경우:
입력:
{"owner": 5, "image": "data:image/jpeg;base64,/9j/4QqdRXhpZgAATU0A..."}
백엔드에서request.data
드라마들.
{u'owner': 5, u'image': u'data:image/jpeg;base64,/9j/4QqdRXhpZgAATU0AKgAAA..."}
그러나ImageSerializer(data=request.data).errors
에러를 나타냅니다.
ReturnDict([('image', [u'The submitted data was not a file. Check the encoding type on the form.'])])
오류를 수정하려면 어떻게 해야 하나요?
편집: JS 부품
관련 프런트 엔드 코드는 다음 두 부분으로 구성됩니다.angular-file-dnd
directive
(여기서 이용 가능) 파일을 페이지에 드롭하고angular-restmod
CRUD 동작은 다음과 같습니다.
<!-- The template: according to angular-file-dnd, -->
<!-- it will store the dropped image into variable $scope.image -->
<div file-dropzone="[image/png, image/jpeg, image/gif]" file="image" class='method' data-max-file-size="3" file-name="imageFileName">
<div layout='row' layout-align='center'>
<i class="fa fa-upload" style='font-size:50px;'></i>
</div>
<div class='text-large'>Drap & drop your photo here</div>
</div>
# A simple `Image` `model` to perform `POST`
$scope.image_resource = Image.$build();
$scope.upload = function() {
console.log("uploading");
$scope.image_resource.image = $scope.image;
$scope.image_resource.owner = Auth.get_profile().user_id;
return $scope.image_resource.$save();
};
문제에 대한 업데이트: 현재 사용으로 전환했습니다.ng-file-upload
이미지 데이터를 올바른 형식으로 전송합니다.
당신이 직면하고 있는 문제는 Django REST 프레임워크가 표준 파일 업로드 방식을 통해 파일이 멀티파트 폼 데이터로 업로드될 것으로 예상한다는 것입니다.이것은 보통 필드이지만 JavaScript 개체는 AJAX에서도 작동합니다.
기본적으로 지원되지 않는 raw 파일이 아닌 base64 인코딩된 문자열을 사용하여 파일을 업로드하려고 합니다.실제 구현도 있지만 가장 유망한 것은 풀 요청을 통해 이루어졌습니다.
대부분 Django REST 프레임워크 2.x용으로 설계되었기 때문에 풀 요청에서 개선하여 DRF 3과 호환되는 것을 만들었습니다.
serializers.py
from rest_framework import serializers
class Base64ImageField(serializers.ImageField):
"""
A Django REST framework field for handling image-uploads through raw post data.
It uses base64 for encoding and decoding the contents of the file.
Heavily based on
https://github.com/tomchristie/django-rest-framework/pull/1268
Updated for Django REST framework 3.
"""
def to_internal_value(self, data):
from django.core.files.base import ContentFile
import base64
import six
import uuid
# Check if this is a base64 string
if isinstance(data, six.string_types):
# Check if the base64 string is in the "data:" format
if 'data:' in data and ';base64,' in data:
# Break out the header from the base64 content
header, data = data.split(';base64,')
# Try to decode the file. Return validation error if it fails.
try:
decoded_file = base64.b64decode(data)
except TypeError:
self.fail('invalid_image')
# Generate file name:
file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
# Get the file name extension:
file_extension = self.get_file_extension(file_name, decoded_file)
complete_file_name = "%s.%s" % (file_name, file_extension, )
data = ContentFile(decoded_file, name=complete_file_name)
return super(Base64ImageField, self).to_internal_value(data)
def get_file_extension(self, file_name, decoded_file):
import imghdr
extension = imghdr.what(file_name, decoded_file)
extension = "jpg" if extension == "jpeg" else extension
return extension
이것은 표준의 대체에 사용되어야 한다.ImageField
Django REST 프레임워크에 의해 제공됩니다.그러면 시리얼라이저는
class ImageSerializer(serializers.ModelSerializer):
image = Base64ImageField(
max_length=None, use_url=True,
)
class Meta:
model = Image
fields = ("id", 'image', 'owner', 'time_created', )
이를 통해 base64로 인코딩된 문자열 또는 표준 문자열을 지정할 수 있습니다.Blob
일반적으로 Django REST 프레임워크가 예상하는 객체입니다.
저는 며칠 전에 같은 문제에 부딪혔어요.파일 업로드를 처리하기 위한 django rest 프레임워크 뷰입니다.
views.py
class PhotoUploadView(APIView):
parser_classes = (FileUploadParser,)
def post(self, request):
user = self.request.user
if not user:
return Response(status=status.HTTP_403_FORBIDDEN)
profile = None
data = None
photo = None
file_form = FileUploadForm(request.POST,request.FILES)
if file_form.is_valid():
photo = request.FILES['file']
else:
return Response(ajax_response(file_form),status=status.HTTP_406_NOT_ACCEPTABLE)
try:
profile = Organizer.objects.get(user=user)
profile.photo = photo
profile.save()
data = OrganizersSerializer(profile).data
except Organizer.DoesNotExist:
profile = Student.objects.get(user=user)
profile.photo = photo
profile.save()
data = StudentsSerializer(profile).data
return Response(data)
프런트 엔드에서 angular-file-upload lib를 사용했습니다.
여기 제 파일 입력이 있습니다.
<div ng-file-drop="" ng-file-select="" ng-model="organizer.photo" class="drop-box" drag-over-class="{accept:'dragover', reject:'dragover-err', delay:100}" ng-multiple="false" allow-dir="true" accept="image/*">
Drop Images or PDFs<div>here</div>
</div>
그리고 여기 제 업로드 서비스가 있습니다.
main.discloss.main.discloss.
(function () {
'use strict';
angular
.module('trulii.utils.services')
.factory('UploadFile', UploadFile);
UploadFile.$inject = ['$cookies', '$http','$upload','$window','Authentication'];
/**
* @namespace Authentication
* @returns {Factory}
*/
function UploadFile($cookies, $http,$upload,$window,Authentication) {
/**
* @name UploadFile
* @desc The Factory to be returned
*/
var UploadFile = {
upload_file: upload_file,
};
return UploadFile;
function upload_file(file) {
return $upload.upload({
url: '/api/users/upload/photo/', // upload.php script, node.js route, or servlet url
//method: 'POST' or 'PUT',
//headers: {'Authorization': 'xxx'}, // only for html5
//withCredentials: true,
file: file, // single file or a list of files. list is only for html5
//fileName: 'doc.jpg' or ['1.jpg', '2.jpg', ...] // to modify the name of the file(s)
//fileFormDataName: myFile, // file formData name ('Content-Disposition'), server side request form name
// could be a list of names for multiple files (html5). Default is 'file'
//formDataAppender: function(formData, key, val){} // customize how data is added to the formData.
// See #40#issuecomment-28612000 for sample code
})
}
}
})();
언급URL : https://stackoverflow.com/questions/28036404/django-rest-framework-upload-image-the-submitted-data-was-not-a-file
'programing' 카테고리의 다른 글
각도 테스트셀레늄이 있는 JS (0) | 2023.03.02 |
---|---|
WordPress + 멀티사이트:Network Admin에서 Add New Site 양식에 커스텀 블로그 옵션을 추가하는 방법 (0) | 2023.03.02 |
html을 반응으로 안전하게 렌더링하는 방법 (0) | 2023.03.02 |
Angular JS - $anchor Scroll 스무스 / 지속시간 (0) | 2023.03.02 |
Wordpress 작성자 URL이 홈 페이지로 리디렉션됨 (0) | 2023.02.25 |