Django Rest框架file upload

我正在使用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) 

作为post方法的最后一行应该返回所有的数据,我有几个问题:

  • 如何检查request.FILES是否有任何内容?
  • 如何序列化文件字段?
  • 我应该如何使用parsing器?

使用FileUploadParser ,这一切都在请求。 使用put方法,你会在文档中find一个例子:)

 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) 

我正在使用相同的堆栈,也正在寻找file upload的例子,但我的情况是更简单,因为我使用ModelViewSet而不是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] }); }; }); 

最后,我可以使用Django上传图片。 这是我的工作代码

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() # ... # 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请求上传

 curl -X POST -S -H -u "admin:password" -F "file=@img.jpg;type=image/jpg" 127.0.0.1:8000/resourceurl/imageUpload 

我用ModelViewSet和ModelSerializer解决了这个问题。 希望这将有助于社区。

我也想在validation和对象 – > JSON(反之亦然)login在序列化器本身,而不是在视图。

让我们通过例子来了解它。

说,我想创buildFileUploader API。 它将在数据库中存储id,file_path,file_name,size,owner等字段。 看下面的示例模型:

 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,这是我想要的:

  1. GET:当我启动GET端点时,我希望每个上传的文件都有上面的字段。

  2. POST:但是为了用户创build/上传文件,为什么她必须担心通过所有这些字段。 她可以上传文件,然后,我想,序列化器可以从上传的文件中获得剩余的字段。

search器: 问题:我创build了下面的序列化器来服务我的目的。 但不确定是否有正确的方法来执行它。

 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 

在django-rest-framework请求数据由Parsersparsing。
http://www.django-rest-framework.org/api-guide/parsers/

默认情况下,django-rest-framework需要parsing器类JSONParser 。 它会将数据parsing成json。 所以,文件将不会被parsing。
如果我们想要文件与其他数据一起parsing,我们应该使用下面的parsing器类之一。

 FormParser MultiPartParser FileUploadParser