Django Rest Framework 파일 업로드
저는 Django Rest Framework와 AngularJs를 사용하여 파일을 업로드하고 있습니다.내 뷰 파일은 다음과 같습니다.
class ProductList(APIView):
authentication_classes = (authentication.TokenAuthentication,)
def get(self,request):
if request.user.is_authenticated():
userCompanyId = request.user.get_profile().companyId
products = Product.objects.filter(company = userCompanyId)
serializer = ProductSerializer(products,many=True)
return Response(serializer.data)
def post(self,request):
serializer = ProductSerializer(data=request.DATA, files=request.FILES)
if serializer.is_valid():
serializer.save()
return Response(data=request.DATA)
마지막 포스트 방법은 모든 데이터를 반환하기 때문에 몇 가지 질문이 있습니다.
- 무엇이
request.FILES - 파일 필드를 직렬화하는 방법
- 파서를 어떻게 사용하면 좋을까요?
편집자 메모:
- 에서는 ""를 사용합니다.
pre_save장고 REST 3.0입니다.- 에서는 Django REST는
MultiPartParser는 기본적으로 사용할 수 있어야 합니다.이것에 의해, 특별한 처리 없이 파일을 업 로드할 수 있습니다.예에 대해서는, 다음의 회답을 참조해 주세요.
같은 스택을 사용하고 있으며 파일 업로드의 예도 찾고 있습니다만, Model View를 사용하고 있기 때문에, 보다 심플하게 할 수 있습니다.APIView 대신 설정.키는 pre_save 훅으로 판명되었습니다.angular-file-upload 모듈과 함께 사용하게 되었습니다.
# Django
class ExperimentViewSet(ModelViewSet):
queryset = Experiment.objects.all()
serializer_class = ExperimentSerializer
def pre_save(self, obj):
obj.samplesheet = self.request.FILES.get('file')
class Experiment(Model):
notes = TextField(blank=True)
samplesheet = FileField(blank=True, default='')
user = ForeignKey(User, related_name='experiments')
class ExperimentSerializer(ModelSerializer):
class Meta:
model = Experiment
fields = ('id', 'notes', 'samplesheet', 'user')
// AngularJS
controller('UploadExperimentCtrl', function($scope, $upload) {
$scope.submit = function(files, exp) {
$upload.upload({
url: '/api/experiments/' + exp.id + '/',
method: 'PUT',
data: {user: exp.user.id},
file: files[0]
});
};
});
FileUploadParser를 사용하면 모든 것이 요청에 포함됩니다.대신 put 방식을 사용하세요.예는 문서에 나와 있습니다.
class FileUploadView(views.APIView):
parser_classes = (FileUploadParser,)
def put(self, request, filename, format=None):
file_obj = request.FILES['file']
# do some stuff with uploaded file
return Response(status=204)
드디어 장고를 사용하여 이미지를 업로드 할 수 있게 되었습니다.여기 작업 코드가 있습니다.
views.py
class FileUploadView(APIView):
parser_classes = (FileUploadParser, )
def post(self, request, format='jpg'):
up_file = request.FILES['file']
destination = open('/Users/Username/' + up_file.name, 'wb+')
for chunk in up_file.chunks():
destination.write(chunk)
destination.close() # File should be closed only after all chuns are added
# ...
# do some stuff with uploaded file
# ...
return Response(up_file.name, status.HTTP_201_CREATED)
urls.py
urlpatterns = patterns('',
url(r'^imageUpload', views.FileUploadView.as_view())
업로드할 컬 요청
curl -X POST -S -H -u "admin:password" -F "file=@img.jpg;type=image/jpg" 127.0.0.1:8000/resourceurl/imageUpload
내 경험상 파일 필드에 대해 특별히 할 필요가 없으며 파일 필드를 활용하도록 지시하기만 하면 됩니다.
from rest_framework import routers, serializers, viewsets
class Photo(django.db.models.Model):
file = django.db.models.ImageField()
def __str__(self):
return self.file.name
class PhotoSerializer(serializers.ModelSerializer):
class Meta:
model = models.Photo
fields = ('id', 'file') # <-- HERE
class PhotoViewSet(viewsets.ModelViewSet):
queryset = models.Photo.objects.all()
serializer_class = PhotoSerializer
router = routers.DefaultRouter()
router.register(r'photos', PhotoViewSet)
api_urlpatterns = ([
url('', include(router.urls)),
], 'api')
urlpatterns += [
url(r'^api/', include(api_urlpatterns)),
]
파일을 업로드할 준비가 되었습니다.
curl -sS http://example.com/api/photos/ -F 'file=@/path/to/file'
-F field=value델델있있있있있있대대대대대대대대대대 。★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
하루 종일 고민하다가 알게 된 건...
파일을 업로드하여 데이터를 전송해야 하는 사용자에게 파일을 바로 사용할 수 있는 방법은 없습니다.이에 대한 JSON API 사양에는 미해결 문제가 있습니다.제가 본 한 가지 가능성은multipart/relatedDRF에서는 구현이 매우 어렵다고 생각합니다.
가 요청한 이었습니다.FormData각 파일을 파일로 전송하고 다른 모든 데이터를 텍스트로 전송합니다.데이터를 텍스트로 전송하려면 두 가지 선택사항이 있습니다.케이스 1) 각 데이터를 키-값 쌍으로 전송하거나 케이스 2) 데이터라는 단일 키를 사용하여 전체 JSON을 값의 문자열로 전송할 수 있습니다.
첫 번째 방법은 단순 필드가 있는 경우 즉시 사용할 수 있지만 중첩된 직렬화가 있는 경우 문제가 됩니다.멀티파트 파서는 중첩된 필드를 구문 분석할 수 없습니다.
이하에, 양쪽의 케이스의 실장을 나타냅니다.
models.py
class Posts(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
caption = models.TextField(max_length=1000)
media = models.ImageField(blank=True, default="", upload_to="posts/")
tags = models.ManyToManyField('Tags', related_name='posts')
serializers.py -> 특별한 변경은 필요 없습니다.쓰기 가능한 Many To Many Field 구현으로 인해 시리얼라이저가 너무 길기 때문에 여기에 표시되지 않습니다.
views.py
class PostsViewset(viewsets.ModelViewSet):
serializer_class = PostsSerializer
#parser_classes = (MultipartJsonParser, parsers.JSONParser) use this if you have simple key value pair as data with no nested serializers
#parser_classes = (parsers.MultipartParser, parsers.JSONParser) use this if you want to parse json in the key value pair data sent
queryset = Posts.objects.all()
lookup_field = 'id'
첫 번째 방법을 따르고 Json 이외의 데이터를 키와 값의 쌍으로만 전송하는 경우에는 커스텀파서 클래스가 필요 없습니다.DRF'd MultipartParser가 작업을 수행합니다.그러나 두 번째 경우 또는 네스트된 시리얼라이저가 있는 경우(표시한 바와 같이) 다음과 같은 커스텀파서가 필요합니다.
utils.py
from django.http import QueryDict
import json
from rest_framework import parsers
class MultipartJsonParser(parsers.MultiPartParser):
def parse(self, stream, media_type=None, parser_context=None):
result = super().parse(
stream,
media_type=media_type,
parser_context=parser_context
)
data = {}
# for case1 with nested serializers
# parse each field with json
for key, value in result.data.items():
if type(value) != str:
data[key] = value
continue
if '{' in value or "[" in value:
try:
data[key] = json.loads(value)
except ValueError:
data[key] = value
else:
data[key] = value
# for case 2
# find the data field and parse it
data = json.loads(result.data["data"])
qdict = QueryDict('', mutable=True)
qdict.update(data)
return parsers.DataAndFiles(qdict, result.files)
이 시리얼라이저는 기본적으로 값의 모든 JSON 콘텐츠를 해석합니다.
두 경우 모두 우체부의 요청 예를 다음에 나타냅니다.
케이스 1

케이스 2

Django Rest Framework용 Model Viewset의 가장 쉬운 예에 관심이 있는 사용자.
모델은 다음과 같습니다.
class MyModel(models.Model):
name = models.CharField(db_column='name', max_length=200, blank=False, null=False, unique=True)
imageUrl = models.FileField(db_column='image_url', blank=True, null=True, upload_to='images/')
class Meta:
managed = True
db_table = 'MyModel'
시리얼라이저,
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = "__all__"
그리고 뷰는
class MyModelView(viewsets.ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
우체국에서의 테스트,
models.py
from django.db import models
import uuid
class File(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
file = models.FileField(blank=False, null=False)
def __str__(self):
return self.file.name
serializers.py
from rest_framework import serializers
from .models import File
class FileSerializer(serializers.ModelSerializer):
class Meta:
model = File
fields = "__all__"
views.py
from django.shortcuts import render
from rest_framework.parsers import FileUploadParser
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
from .serializers import FileSerializer
class FileUploadView(APIView):
permission_classes = []
parser_class = (FileUploadParser,)
def post(self, request, *args, **kwargs):
file_serializer = FileSerializer(data=request.data)
if file_serializer.is_valid():
file_serializer.save()
return Response(file_serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(file_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
urls.py
from apps.files import views as FileViews
urlpatterns = [
path('api/files', FileViews.FileUploadView.as_view()),
]
설정을 지정합니다.화이
# file uload parameters
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
을 고고고 send send send send send로 송신하다api/files하여 ""에 하여''form-data 들 fieldfile이 업로드 /mediaDB ID입니다.
이 문제를 Model View로 해결했습니다.및 ModelSerializer를 설정합니다.이것이 지역사회에 도움이 되기를 바랍니다.
또, 검증과 오브젝트-> JSON(및 그 반대) 로그인을 뷰가 아닌 시리얼라이저로 하는 것도 추천합니다.
그것을 예로 들어 이해합시다.
예를 들어 FileUploader API를 만들고 싶습니다.ID, file_path, file_name, 크기, 소유자 등의 필드를 데이터베이스에 저장합니다.아래 샘플 모델을 참조하십시오.
class FileUploader(models.Model):
file = models.FileField()
name = models.CharField(max_length=100) #name is filename without extension
version = models.IntegerField(default=0)
upload_date = models.DateTimeField(auto_now=True, db_index=True)
owner = models.ForeignKey('auth.User', related_name='uploaded_files')
size = models.IntegerField(default=0)
API는 다음과 같습니다.
- 취득:
GET 엔드포인트를 실행할 때 업로드된 모든 파일에 대해 위의 모든 필드가 필요합니다.
- 투고:
그러나 사용자가 파일을 작성/업로드하려면 이러한 모든 필드를 넘겨야 하는 이유를 알아야 합니다.파일을 업로드하면 시리얼라이저는 업로드된 FILE에서 나머지 필드를 가져올 수 있습니다.
서라이저:질문:목적에 맞게 아래 시리얼라이저를 만들었습니다.하지만 이것이 그것을 구현하는 올바른 방법인지 확실하지 않다.
class FileUploaderSerializer(serializers.ModelSerializer):
# overwrite = serializers.BooleanField()
class Meta:
model = FileUploader
fields = ('file','name','version','upload_date', 'size')
read_only_fields = ('name','version','owner','upload_date', 'size')
def validate(self, validated_data):
validated_data['owner'] = self.context['request'].user
validated_data['name'] = os.path.splitext(validated_data['file'].name)[0]
validated_data['size'] = validated_data['file'].size
#other validation logic
return validated_data
def create(self, validated_data):
return FileUploader.objects.create(**validated_data)
참조용 뷰 세트:
class FileUploaderViewSet(viewsets.ModelViewSet):
serializer_class = FileUploaderSerializer
parser_classes = (MultiPartParser, FormParser,)
# overriding default query set
queryset = LayerFile.objects.all()
def get_queryset(self, *args, **kwargs):
qs = super(FileUploaderViewSet, self).get_queryset(*args, **kwargs)
qs = qs.filter(owner=self.request.user)
return qs
더 깨끗하고 유지보수가 쉽다고 느끼는 다른 옵션을 쓰고 싶습니다.defaultRouter를 사용하여 뷰셋의 CRUD URL을 추가하고 동일한 뷰셋 내에서 업로더 뷰를 지정하는 고정 URL을 하나 더 추가합니다.
**** views.py
from rest_framework import viewsets, serializers
from rest_framework.decorators import action, parser_classes
from rest_framework.parsers import JSONParser, MultiPartParser
from rest_framework.response import Response
from rest_framework_csv.parsers import CSVParser
from posts.models import Post
from posts.serializers import PostSerializer
class PostsViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
parser_classes = (JSONParser, MultiPartParser, CSVParser)
@action(detail=False, methods=['put'], name='Uploader View', parser_classes=[CSVParser],)
def uploader(self, request, filename, format=None):
# Parsed data will be returned within the request object by accessing 'data' attr
_data = request.data
return Response(status=204)
프로젝트의 주요 URL.화이
**** urls.py
from rest_framework import routers
from posts.views import PostsViewSet
router = routers.DefaultRouter()
router.register(r'posts', PostsViewSet)
urlpatterns = [
url(r'^posts/uploader/(?P<filename>[^/]+)$', PostsViewSet.as_view({'put': 'uploader'}), name='posts_uploader')
url(r'^', include(router.urls), name='root-api'),
url('admin/', admin.site.urls),
]
.-README
@action decorator를 클래스 메서드 'uploader'에 추가하면 마법이 발생합니다."put=['put'" 인수를 지정함으로써 PUT 요청만 허용하므로 파일 업로드에 적합합니다.
또한 "parser_classes" 인수를 추가하여 콘텐츠를 해석할 파서를 선택할 수 있습니다.rest_framework_csv 패키지에서 CSVParser를 추가했습니다.이 기능이 필요한 경우 특정 유형의 파일만 받을 수 있다는 것을 보여주기 위해 저는 "Content-Type: text/csv"만 받습니다.주의: 커스텀 파서를 추가할 경우 ViewSet의 parsers_classes에 지정해야 합니다.이는 업로더 메서드 파서에 액세스하기 전에 요청이 허용된 media_type과 메인(클래스) 파서를 비교하기 때문입니다.
이제 이 방법을 사용하는 방법과 URL에서 구현할 수 있는 위치를 Django에게 알려야 합니다.이 때 고정 URL을 추가합니다(간단한 목적).이 URL은 나중에 메서드에서 전달될 "filename" 인수를 사용합니다.리스트 내의 http protocol('PUT')을 지정하는 이 메서드를 PostsViewSet.as_view 메서드에 전달해야 합니다.
다음 URL에 도착하면
http://example.com/posts/uploader/
"Content-Type" 및 "Content-Disposition: attachment; filename="something.csv" 헤더가 지정된 PUT 요청을 예상합니다.
curl -v -u user:pass http://example.com/posts/uploader/ --upload-file ./something.csv --header "Content-type:text/csv"
일부 솔루션은 권장되지 않습니다(Django 3.0+에는 request.data를 사용해야 합니다).그 중 일부는 입력의 유효성을 검사하지 않습니다.또, swager annotation이 있는 솔루션을 주시면 감사하겠습니다.따라서 다음 코드를 사용할 것을 권장합니다.
from drf_yasg.utils import swagger_auto_schema
from rest_framework import serializers
from rest_framework.parsers import MultiPartParser
from rest_framework.response import Response
from rest_framework.views import APIView
class FileUploadAPI(APIView):
parser_classes = (MultiPartParser, )
class InputSerializer(serializers.Serializer):
image = serializers.ImageField()
@swagger_auto_schema(
request_body=InputSerializer
)
def put(self, request):
input_serializer = self.InputSerializer(data=request.data)
input_serializer.is_valid(raise_exception=True)
# process file
file = input_serializer.validated_data['image']
return Response(status=204)
이 뷰를 사용하여 파일을 aws에 업로드했습니다.여기서 upload_file은 도우미 기능입니다.전체적으로 이 뷰를 사용하여 파일을 폼 데이터로 업로드 할 수 있습니다.
class FileUploadView(GenericAPIView):
def post(self, request):
try:
file = request.data['file']
if file.content_type == 'image/png' or file.content_type == 'image/jpeg':
file_name = upload_file(file)
return Response({"name": file_name}, status=status.HTTP_202_ACCEPTED)
else:
raise UnsupportedMediaType(file.content_type)
except KeyError:
return Response("file missing.", status=status.HTTP_404_NOT_FOUND)
단일 업로드 파일 또는 여러 파일을 단일 요청으로 처리하는 가장 간단한 방법은 다음과 같습니다.
@api_view(['POST'])
def file_list(request): # use APIview or function based view or any view u want
# for single file
file = request.FILES["file"]
print(file)
# Do what ever you want with it
# for multiple file
files = request.FILES.getlist('file')
for file in files:
print(file)
# Do what ever you want with it
from rest_framework import status
from rest_framework.response import Response
class FileUpload(APIView):
def put(request):
try:
file = request.FILES['filename']
#now upload to s3 bucket or your media file
except Exception as e:
print e
return Response(status,
status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response(status, status.HTTP_200_OK)
모델뷰Set을 사용하고 있다면, 실제로는 이것으로 끝입니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★! ModelSerializer를 설정하기만 하면 .content-type=multipart/form-data;를 참조해 주세요.
하지만 아시다시피 json 포맷으로 파일을 보낼 수 없습니다.(클라이언트에서 content-type이 application/json으로 설정되어 있는 경우).Base64 형식을 사용하지 않는 한.
두 가지 선택지가 있습니다.
- 를 놓다
ModelViewSetand 그리고.ModelSerializerhandle the job and send the request using 작업을 처리하여 요청을 전송합니다.content-type=multipart/form-data; - 비 하에서 필드를 설정합니다.
ModelSerializeras ~하듯이Base64ImageField (or) Base64FileFieldand tell your client to encode the file to 클라이언트에 파일을 부호화하도록 지시합니다.Base64and set the 를 설정합니다.content-type=application/json
from rest_framework import status, generics
from rest_framework.response import Response
from rest_framework import serializers
import logging
logger = logging.getLogger(__name__)`enter code here`
class ImageUploadSerializer(serializers.Serializer):
file = serializers.FileField()
class UploadImages(generics.GenericAPIView):
serializer_class = ImageUploadSerializer
permission_classes = [IsAuthenticated, ]
def post(self, request):
try:
data = self.serializer_class(data=request.data)
if data.is_valid() is False:
return Response({'error': ERROR_MESSAGES.get('400')}, status=status.HTTP_400_BAD_REQUEST)
is_file_upload_success, file_item = save_aws_article_image(data.validated_data.get('file'),
request.user, upload_type)
if is_file_upload_success:
logger.info('{0} file uploaded {1}'.format(file_item['file_obj'].path, datetime.now()))
return Response({'path': file_item['file_obj'].path, 'id': file_item['file_obj'].uuid,
'name': file_item['file_obj'].name},
status=status.HTTP_201_CREATED)
except Exception as e:
logger.error(e, exc_info=True)
return Response({"error": e}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
o 흥미로운 프레임워크 요청 데이터는 o 구 이 해 석 터 해 됩 의 니 in다 d-에에 request--jang is datajangframework데rest요는 pars-framework theParsers.
http://www.django-rest-framework.org/api-guide/parsers/http: www.django-rest-framework.org/api-guide/parsers/: :
"django-rest-framework" 를 합니다.JSONParser데이터를 json으로 해석하기 때문에 파일은 해석되지 않습니다.
다른 데이터와 함께 파일을 구문 분석하려면 다음 구문 분석기 클래스 중 하나를 사용해야 합니다.
FormParser
MultiPartParser
FileUploadParser
def post(self,request):
serializer = ProductSerializer(data=request.DATA, files=request.FILES)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
이것이 도움이 되기를 바라며 제가 적용한 접근법 중 하나입니다.
class Model_File_update(APIView):
parser_classes = (MultiPartParser, FormParser)
permission_classes = [IsAuthenticated] # it will check if the user is authenticated or not
authentication_classes = [JSONWebTokenAuthentication] # it will authenticate the person by JSON web token
def put(self, request):
id = request.GET.get('id')
obj = Model.objects.get(id=id)
serializer = Model_Upload_Serializer(obj, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=200)
else:
return Response(serializer.errors, status=400)
파서 클래스를 생성하여 특정 필드를 해석하고 표준 DRF 시리얼라이저에 직접 공급함으로써 @Nithin의 응답을 DRF의 기존 시리얼라이저 시스템과 직접 연계할 수 있습니다.
from django.http import QueryDict
import json
from rest_framework import parsers
def gen_MultipartJsonParser(json_fields):
class MultipartJsonParser(parsers.MultiPartParser):
def parse(self, stream, media_type=None, parser_context=None):
result = super().parse(
stream,
media_type=media_type,
parser_context=parser_context
)
data = {}
# find the data field and parse it
qdict = QueryDict('', mutable=True)
for json_field in json_fields:
json_data = result.data.get(json_field, None)
if not json_data:
continue
data = json.loads(json_data)
if type(data) == list:
for d in data:
qdict.update({json_field: d})
else:
qdict.update({json_field: data})
return parsers.DataAndFiles(qdict, result.files)
return MultipartJsonParser
이것은 다음과 같이 사용됩니다.
class MyFileViewSet(ModelViewSet):
parser_classes = [gen_MultipartJsonParser(['tags', 'permissions'])]
# ^^^^^^^^^^^^^^^^^^^
# Fields that need to be further JSON parsed
....
DRF 뷰셋파일은 react(axios)를 사용하여 audioBlob을 전송하기 위한 예를 업로드합니다.
class MyViewSet(viewsets.ModelViewSet):
parser_classes = (MultiPartParser, FormParser)
queryset = MyModel.objects.all().order_by('created_at')
serializer_class = MySerializer
시리얼라이저:
class MySerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = '__all__'
모델:
class MyModel(models.Model):
sentence = models.ForeignKey(Sentence, related_name="voice_sentence", on_delete=models.CASCADE)
voice_record = models.FileField(blank=True, default='')
created_at = models.DateTimeField(auto_now_add=True)
악리:
export const sendSpeechText = async (audioBlob: any) => {
const headers = {
'Content-Type': 'application/json',
'Content-Disposition': 'attachment; filename=audiofile.webm'
}
const audiofile = new File([audioBlob], "audiofile.webm", { type: "audio/webm" })
const formData = new FormData();
formData.append("sentence", '1');
formData.append("voice_record", audiofile);
return await axios.post(
SEND_SPEECH_URL,
formData,
{
crossDomain: true,
headers: headers
},
)
}
메모: formData의 voice_record는 모델 내에서 동일해야 합니다.
drf에서 파일을 업로드하는 방법은 크게 3가지입니다.
제목 및 로고 필드가 있는 태그 모델과 TagSerializer가 있다고 가정합니다.
class Tag(models.Model):
title = models.CharField(max_length=10, default='')
file = models.FileField(upload_to='tag/', blank=True, null=True, )
class TagSerializer(rest_serializers.ModelSerializer):
class Meta:
model = Tag
fields = '__all__'
상황에 맞게 하나를 선택하시면 됩니다.
1- 시리얼라이저 사용:
class UploadFile(APIView):
parser_classes = (MultiPartParser, FormParser)
def post(self, request):
serializer = TagSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
2- 쓰기 방법 사용:
def save_file(file: InMemoryUploadedFile, full_path):
with open(full_path, 'wb+') as f:
for chunk in file.chunks():
f.write(chunk)
class UploadFile(APIView):
parser_classes = (MultiPartParser, FormParser)
def post(self, request):
file: InMemoryUploadedFile = request.FILES['file']
# define file_save_path variable
full_path = file_save_path + file.name
save_file(file, full_path)
return Response(serializer.data, status=status.HTTP_200_OK)
3- File System Storage 사용:
class UploadFile(APIView):
parser_classes = (MultiPartParser, FormParser)
def post(self, request):
file: InMemoryUploadedFile = request.FILES['file']
f = FileSystemStorage()
# this will save file in MEDIA_ROOT path
f.save(file.name, file)
return Response(serializer.data, status=status.HTTP_200_OK)
파일 업로드에 기능 기반 보기를 사용하거나 선호하는 사용자용.
이 가이드는 [Creating Models]> [ views ]> [ Serializers ]> [ URLs ]및 [Postman]에 의한 엔드포인트 테스트]의 완전한 가이드입니다.필요한 경우 코드에 코멘트를 넣었습니다.
# models.py
# Imports
from django.db import models
import os
def document_path_and_name(instance, filename):
''' Change the filename to 'instance_id + document_name '''
ext = filename.split('.')[-1]
filename = "%s_%s.%s" % (instance.id, instance.document_name, ext)
''' if document_name is 'doucment one' in pdf and id is 1
then filname will be saved as = 1_document_one.pdf '''
return os.path.join('files/', filename)
class Document(models.Model):
# I'm using document_name and id to give the filename that would be save with
# this using document_path_and_name function.
# you can modify on your need.
document_name = models.CharField(max_length=100)
file = models.FileField(upload_to=document_path_and_name)
def __str__(self):
return self.document_name
여기서 파일 업로드를 검증하는 데 시리얼라이저는 필요 없습니다만, 응답을 시리얼화할 필요가 있는 경우는 필요합니다.이 경우는, 심플한 Read Only Serializer 를 사용해 보겠습니다.
# serializers.py
# imports
from rest_framework import serializers
class DocumentSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
document_name = serializers.CharField(read_only=True)
file = serializers.URLField(read_only=True)
재,에서api_view 그럼 에는 을 하겠습니다.MultiPartParser데코레이터를 사용하여 POST 요청을 통해 파일을 업로드합니다.는 ★★★★★★★★★★★★★★★★★★★★★★★★.document_name모델을 설정한 대로 파일을 올바르게 업로드 할 수 있는 파일입니다.
# views.py
# imports
from rest_framework.decorators import api_view, parser_classes
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser
from .models import Document
from .serializers import DocumentSerializer
@api_view(['POST'])
@parser_classes([MultiPartParser])
def upload_document(request, filename, format=None):
"""
A view that can accept POST requests with .media_type: multipart/form-data content.
"""
file = request.FILES['file']
doc = Document.objects.create(document_name=filename, file=file)
# Do any thing else here
serializer = DocumentSerializer(doc, many=False)
return Response(serializer.data)
.document_name할 수 있지만 했습니다.filenameAPI Endpoint "URL" "URL" "URL" "URL" "URL" "URL" "URL" "URL" 입니다.
# imports
from django.urls import path
from .views import upload_document
urlpatterns = [
path('upload_document/<str:filename>/', upload_document),
]
따라서 Postman을 통해 테스트하려면 다음과 같이 유효한 API 엔드포인트로 이동하십시오.
document_name은 이든 전달할 수 .아래 스크린샷에서 실제 파일 이름이 pdf 형식 이외의 것임을 알 수 있습니다.은 우리 회사의 입니다.document_path_and_nameid_syslog_name으로 합니다.저장 파일명은 다음과 같습니다.1_filename.pdf
이제 요청만 하면 파일이 다이렉트 파일 스토리지 경로에 업로드됩니다."DocumentSerializer" "JSON Response" "DocumentSerializer" 입니다.는 '파일 업로드'입니다.MultiPartParser데코레이터자세한 내용은 문서를 참조하십시오.
ViewSets를 사용하는 경우 파일 업로드를 처리하는 사용자 지정 작업을 추가할 수 있습니다.
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.parsers import FileUploadParser
from rest_framework import viewsets
...
class SomeViewSet(viewsets.ModelViewSet):
serializer_class = ...
permission_classes = [...]
queryset = ...
@action(methods=['put'], detail=True, parser_classes=[FileUploadParser])
def upload_file(self, request, pk=None):
obj = self.get_object()
obj.file = request.data['file']
obj.save()
return Response(status=204)
[ View Set ]를 선택합니다.api/item/32/upload_file/.
를 사용하는 이유FileUploadParser멀티 파트와 같은 다른 옵션과는 달리 멀티 파트 인코더에 의존하지 않고 네이티브 앱에서 업로드하는 경우입니다.
언급URL : https://stackoverflow.com/questions/20473572/django-rest-framework-file-upload
'codememo' 카테고리의 다른 글
| 오류 'babel-core' 모듈을 찾을 수 없습니다.react.displays, webpack 및 express 서버 사용 (0) | 2023.03.19 |
|---|---|
| 아이템이 존재하는지 테스트하기 위해 MongoDB에 문의하는 방법 (0) | 2023.03.19 |
| Oracle에서 변수를 선언하고 표시하는 방법 (0) | 2023.03.14 |
| angular.module()을 여러 번 정의하는 AngularJS (0) | 2023.03.14 |
| material ui에서 수평 스크롤이 발생합니다. - (0) | 2023.03.14 |

