2013-12-09 18 views
41

私はDjango Rest FrameworkとAngularJsを使用してファイルをアップロードしています。マイビューファイルは、次のようになります。何がrequest.FILESであっあるかどうかを確認する方法をDjango Rest Frameworkファイルアップロード

  • :POSTメソッドの最後の行は、すべてのデータを返す必要がありますとして

    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) 
    

    、私はいくつかの質問がありますか?

  • ファイルフィールドをシリアル化する方法は?
  • パーサーはどのように使用しますか?

答えて

31

FileUploadParserを使用してください。リクエストに含まれています。 はあなたにもファイルアップロードの例を探していたドキュメント:)私は同じスタックを使用してい

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) 
+0

ねえ、あなたは私がhttp://stackoverflow.com/questions/26673572/django-rest-framework-upload-file-to-a-methodを解決できる方法を知っていますか? – psychok7

+2

POSTの代わりにここでPUTメソッドが使用されているのはなぜですか? – RTan

+0

@Regoこれをチェックしてくださいhttp://stackoverflow.com/a/14402607/361427 :) – pleasedontbelong

45

の例を見つけることができます、代わりにputメソッドを使用しますが、私の場合は、I以来、単純ですAPIViewの代わりにModelViewSetを使用します。キーはpre_saveフックであることが判明しました。私は角ファイルアップロードモジュールと一緒にこのように使用しました。

# 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] 
     }); 
    }; 
}); 
+1

ありがとう!優れた(そして非常に完全な)リファレンス! – WhyNotHugo

+3

pre_saveはdrf 3.xで非推奨です –

18

最後に私は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私はModelViewSetとModelSerializerでこの問題を解決し

curl -X POST -S -H -u "admin:password" -F "[email protected];type=image/jpg" 127.0.0.1:8000/resourceurl/imageUpload 
+11

なぜdestination.close()がforループの内側に配置されていますか? – makerj

+4

open( '/ Users/Username /' + up_file.name、 'wb +')を宛先として使用する方が良いと思われます。 –

2

アップロードする

urlpatterns = patterns('', 
url(r'^imageUpload', views.FileUploadView.as_view()) 

カールの要求です。これがコミュニティに役立つことを願っています。

また、ビューではなくシリアライザ自体で、検証とObject-> JSON(およびその逆)ログインを行うことを前提としています。

例としてご理解ください。

と言って、私はFileUploader 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: ユーザーがファイルを作成/アップロードするには、なぜこれらのフィールドをすべて渡すか心配する必要があります。彼女はファイルをアップロードするだけで、シリアライザはアップロードされたFILEから残りのフィールドを取得できると思います。

Searilizer: 質問:私は自分の目的を果たすためにシリアライザの下に作成しました。しかし、それを実装する正しい方法があるかどうかは分かりません。参考のため

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 
0

Parsersによって解析されます。
http://www.django-rest-framework.org/api-guide/parsers/

デフォルトでは、django-rest-frameworkはパーサークラスJSONParserを使用します。それはjsonにデータを解析します。したがって、ファイルは解析されません。
ファイルを他のデータと一緒に解析するには、以下のパーサークラスのいずれかを使用する必要があります。

FormParser 
MultiPartParser 
FileUploadParser 
関連する問題