Django Rest Framework Dosya Yüklemesi


101

Bir dosya yüklemek için Django Rest Framework ve AngularJs kullanıyorum. Görünüm dosyam şöyle görünüyor:

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)

Gönderme yönteminin son satırı tüm verileri döndürmesi gerektiğinden, birkaç sorum var:

  • içinde bir şey olup olmadığını nasıl kontrol edebilirim request.FILES?
  • dosya alanı nasıl serileştirilir?
  • nasıl ayrıştırıcı kullanmalıyım?

15
SADECE MODLARA BİR NOT: Django 2013'ten beri büyük ölçüde yükseldi. Yani şimdi aynı soruyu başka biri sorarsa. LÜTFEN onları ^ _ ^ vurmayın.
Jessi

Base64'e ne dersiniz?
Hojat Modaresi

Yanıtlar:


68

FileUploadParser'ı kullanın, hepsi istek içinde. Bunun yerine bir koyma yöntemi kullanın, belgelerde bir örnek bulacaksınız :)

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)

12
@pleasedontbelong neden burada POST yerine PUT yöntemi kullanıldı?
Md. Tanvir Raihan

8
hi @pleasedontbelong, eğer yeni bir kayıt oluşturuyorsa, bunun yerine POST mu olur? ve yine de FileUploadParser ile çalışacak mı?
chrizonline

1
@pleasedontbelong RTan oldukça güzel bir soru soruyor. RFC-2616'yı okumak, şimdiye kadar farkında olmadığım bir incelik sağlıyor. "POST ve PUT istekleri arasındaki temel fark, İstek URI'sinin farklı anlamında yansıtılır. Bir POST isteğindeki URI, ekteki varlığı işleyecek kaynağı tanımlar. Bu kaynak, bir veri kabul süreci, bir ağ geçidi olabilir. başka bir protokole veya ek açıklamaları kabul eden ayrı bir varlığa. Bunun aksine, bir PUT isteğindeki URI, istekle
eklenen

3
Neden FileUploadParser? "FileUploadParser, dosyayı ham veri isteği olarak yükleyebilen yerel istemcilerle kullanım içindir. Web tabanlı yüklemeler için veya çok parçalı karşıya yükleme desteği olan yerel istemciler için bunun yerine MultiPartParser ayrıştırıcısını kullanmalısınız." Genel olarak iyi bir seçenek gibi görünmüyor. Dahası, belirli bir işleme ihtiyaç duyan dosya yüklemeleri görmüyorum .
x-yuri

3
İkinci @ x-yuri'ye göre DRF, FileUploadParser'ı kullandığımda Content-Disposition başlığının boş olduğundan şikayet ediyor. MultiPartParser, dosya adının Form alanlarında verilen dosya adı olduğunu varsaydığından çok daha basittir.
David Zwart

76

Aynı yığını kullanıyorum ve ayrıca bir dosya yükleme örneği arıyordum, ancak APIView yerine ModelViewSet'i kullandığım için durumum daha basit. Anahtarın ön kaydetme kancası olduğu ortaya çıktı. Açısal dosya yükleme modülüyle birlikte şu şekilde kullandım:

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

11
pre_save drf 3.x sürümünde kullanımdan kaldırıldı
Guy S

Tecrübelerime göre, dosya alanları için özel bir işleme gerek yoktur .
x-yuri

@ Guy-S, perform_create, perform_update, perform_destroy yöntemleri, artık mevcut olmayan eski stil sürüm 2.x pre_save, post_save, pre_delete ve post_delete yöntemlerinin yerini alıyor
Rufat

38

Sonunda Django kullanarak resim yükleyebiliyorum. İşte çalışma kodum

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())

yükleme için curl isteği

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

14
neden destination.close () for döngüsünün içine yerleştirilir?
makerj

12
Kapanışı with open('/Users/Username/' + up_file.name, 'wb+') as destination:tamamen kullanmak ve kaldırmak daha iyi olacak gibi görünüyor
Chuck Wilbur

Kullanımı daha basit ModelViewSet. Ayrıca, büyük olasılıkla daha iyi uyguladılar.
x-yuri

1
Tüm gün boyunca bu cevaba güveniyordum ... ta ki birden fazla dosya yüklemek istediğinizde buna FileUploadParsergerek olmadığını anlayıncaya kadar MultiPartParser!
Olivier Pons

13

Bunun için 1 gün geçirdikten sonra anladım ki ...

Bir dosya yüklemesi ve bazı verileri göndermesi gereken biri için, onu çalıştırmanın doğrudan bir yolu yoktur. Bunun için json api özelliklerinde açık bir sorun var . Gördüğüm bir olasılık, buradamultipart/related gösterildiği gibi kullanmak , ancak bence bunu drf'de uygulamak çok zor.

Sonunda uyguladığım şey, isteği olarak göndermekti formdata. Sen her dosyayı göndereceği dosyanın ve metin gibi tüm diğer veriler. Şimdi verileri metin olarak göndermek için iki seçeneğiniz var. durum 1) her veriyi anahtar değer çifti olarak gönderebilir veya durum 2) veri adı verilen tek bir anahtara sahip olabilir ve tüm json'u değer dizisi olarak gönderebilirsiniz.

İlk yöntem, basit alanlarınız varsa kutudan çıkar, ancak iç içe serileştirmeleriniz varsa bir sorun olacaktır. Çok parçalı ayrıştırıcı, iç içe geçmiş alanları ayrıştıramaz.

Aşağıda her iki durum için de uygulama sağlıyorum

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 -> özel bir değişikliğe gerek yok, yazılabilir ManyToMany Field uygulaması nedeniyle burada serileştiricimi çok uzun olarak göstermiyorum.

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'

Şimdi, ilk yöntemi takip ediyorsanız ve yalnızca anahtar değer çiftleri olarak Json olmayan verileri gönderiyorsanız, özel bir ayrıştırıcı sınıfına ihtiyacınız yoktur. DRF’li MultipartParser işi yapacak. Ancak ikinci durum için veya iç içe diziselleştiricileriniz varsa (gösterdiğim gibi), aşağıda gösterildiği gibi özel ayrıştırıcıya ihtiyacınız olacaktır.

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)

Bu serileştirici, temelde değerlerdeki herhangi bir json içeriğini ayrıştırır.

Her iki durum için post man'daki istek örneği: vaka 1 dava 1 ,

Durum 2 durum2


Durum 2'den kaçınmayı tercih ederim. İstek başına bir veritabanı kaydı oluşturmak çoğu zaman iyi olur.
x-yuri

çok yardımcı çok teşekkür ederim. Ama anlamıyorum, neden dikte verilerini ayrıştırıcıda QueryDict'e dönüştürüyorsunuz? Django'daki durumumda, normal sözlük verileri dönüştürülmeden mükemmel çalışıyor.
Metehan Gülaç

Bahsettiğiniz cevabı kullanarak farklı bir senaryo denedim ve başarılı bir şekilde çalışıyor. Benim bakabilirsiniz cevap .
Metehan Gülaç

eğer bu çalışırsa stackoverflow.com/questions/64547729/… de çalışmalıdır. ama işe yaramaz.
sadat

9

Tecrübelerime göre, dosya alanları hakkında belirli bir şey yapmanıza gerek yok, sadece dosya alanını kullanmasını söylüyorsunuz:

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)),
]

ve dosyaları yüklemeye hazırsınız:

curl -sS http://example.com/api/photos/ -F 'file=@/path/to/file'

Ekle -F field=valuemodeliniz var fazladan her alan için. Ve kimlik doğrulama eklemeyi unutmayın.


7

Bu sorunu ModelViewSet ve ModelSerializer ile çözdüm. Umarım bu topluma yardımcı olur.

Ayrıca, görünümler yerine serileştiricinin kendisinde doğrulama ve Object-> JSON (ve tersi) oturum açmayı tercih ediyorum.

Örnek olarak anlayalım.

Diyelim ki, FileUploader API oluşturmak istiyorum. İd, dosya_yolu, dosya_adı, boyut, sahip vb. Alanları veritabanında depolayacağı yer. Aşağıdaki örnek modele bakın:

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)

Şimdi, API'ler için istediğim şey bu:

  1. ALMAK:

GET uç noktasını çalıştırdığımda, yüklenen her dosya için yukarıdaki tüm alanların olmasını istiyorum.

  1. İLETİ:

Ancak kullanıcının dosya oluşturması / yüklemesi için neden tüm bu alanları geçme konusunda endişelenmesi gerektiği. Sadece dosyayı yükleyebilir ve sanırım serileştirici geri kalan alanları yüklenen FILE'dan alabilir.

Searilizer: Soru: Amacıma hizmet etmek için aşağıdaki serileştiriciyi oluşturdum. Ancak bunu uygulamanın doğru yolu olup olmadığından emin değilim.

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)

Referans için görünüm kümesi:

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

1
FileUploaderSerializer.validateYöntem hangi doğrulama mantığını içerir?
x-yuri

6

Django Rest Framework için ModelViewset ile en kolay örnekle ilgilenen varsa.

Model,

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'

Serileştirici,

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = "__all__"

Ve Görünüm,

class MyModelView(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

Postacıda Test,

görüntü açıklamasını buraya girin


Ve ajax kullanarak talebi nasıl gönderebiliriz? İmageUrl aslında nedir?
Eduard Grigoryev

imageUrl, istekteki dosyadır.
sadat

2

Daha temiz ve bakımı daha kolay olduğunu düşündüğüm başka bir seçenek yazmak istiyorum. Görünüm kümemiz için CRUD url'leri eklemek için defaultRouter'ı kullanacağız ve aynı görünüm kümesi içinde yükleyici görünümünü belirten bir sabit url daha ekleyeceğiz.

**** 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)

Projenin ana url'leri.py

**** 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.

Sihir, sınıf yöntemimiz olan 'yükleyiciye' @action decorator eklediğimizde gerçekleşir. "Yöntemler = ['koy']" bağımsız değişkenini belirterek, yalnızca PUT isteklerine izin veriyoruz; dosya yüklemek için mükemmel.

İçeriğinizi ayrıştıracak ayrıştırıcıyı seçebileceğinizi göstermek için "parser_classes" bağımsız değişkenini de ekledim. Bu işlevsellik gerekliyse yalnızca belirli dosya türlerini nasıl kabul edebileceğimizi göstermek için rest_framework_csv paketinden CSVParser'ı ekledim, benim durumumda yalnızca "Content-Type: text / csv" kabul ediyorum. Not: Özel Ayrıştırıcılar ekliyorsanız, bunları ViewSet içindeki ayrıştırıcı_ sınıflarında belirtmeniz gerekir, çünkü istek, yükleyici yöntemi ayrıştırıcılarına erişmeden önce izin verilen media_type ile ana (sınıf) ayrıştırıcıları karşılaştırır.

Şimdi Django'ya bu yönteme nasıl gidileceğini ve url'lerimizde nerede uygulanabileceğini söylememiz gerekiyor. İşte o zaman sabit url'yi ekliyoruz (Basit amaçlar). Bu URL, daha sonra yönteme iletilecek bir "dosya adı" bağımsız değişkeni alacaktır. Bir listede http protokolünü ('PUT') belirterek "yükleyici" yöntemini PostsViewSet.as_view yöntemine geçirmemiz gerekir.

Aşağıdaki url'ye geldiğimizde

 http://example.com/posts/uploader/ 

"Content-Type" ve Content-Disposition: attachment belirten başlıklara sahip bir PUT isteği bekleyecektir; dosyaadı = "birşey.csv".

curl -v -u user:pass http://example.com/posts/uploader/ --upload-file ./something.csv --header "Content-type:text/csv"

Bu nedenle, bir dosya yüklemenizi ve ardından onu bir db kaydına eklemenizi önerirsiniz. Ya herhangi bir nedenle iliştirme asla olmazsa? Neden tek istekte yapmıyorsunuz? parser_classeshangi dosyaların yüklenebileceğini sınırlamak için orada değildir. İstek yapmak için hangi formatların kullanılabileceğine karar verelim. İkinci kez düşündüğümüzde, yüklemeyi ele alma şekliniz ... CSV'den veri tabanına veri koyuyorsunuz gibi görünüyor. OP'nin sorduğu değil.
x-yuri

@ x-yuri "CSV bir dosyadır" diyerek sorulacak soru ise; İstekte veri olup olmadığı nasıl kontrol edilir? Bu yöntemi kullanarak, verileri request.data'da bulacaksınız. _data = PUT süresi dolan request.data kullanılıyor. Söylediğiniz gibi, parser_classes hangi formatların istek yapmak için kullanılabileceğine karar vermek için oradadır, bu nedenle istemediğiniz başka bir formatı kullanarak, ekstra bir güvenlik katmanı ekleyerek hariç tutulacaktır. Verilerinizle ne yapacağınız size kalmış. "Hariç Dene" yi kullanarak "eklemenin hiçbir zaman gerçekleşmediğini" kontrol edebilirsiniz, ancak buna gerek yoktur, kodun yaptığı bu değildir. Bunlar 1 istekte yapıldı
Wolfgang Leon

1
    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)

1
def post(self,request):
        serializer = ProductSerializer(data=request.DATA, files=request.FILES)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)

1

ModelViewSet kullanıyorsanız, aslında işiniz bitti! Sizin için her şeyi halleder! Alanı ModelSerializer'ınıza koymanız ve content-type=multipart/form-data;istemcinizde ayarlamanız yeterlidir .

ANCAK bildiğiniz gibi json formatında dosya gönderemezsiniz. (içerik türü istemcinizde application / json olarak ayarlandığında). Base64 formatını kullanmadığınız sürece.

Yani iki seçeneğiniz var:

  • izin verin ModelViewSetve ModelSerializerişi halledin ve kullanarak isteği gönderincontent-type=multipart/form-data;
  • alanı ModelSerializerolarak ayarlayın ve Base64ImageField (or) Base64FileFieldmüşterinize dosyayı kodlamasını Base64vecontent-type=application/json

1

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()),
]

settings.py

# file uload parameters
MEDIA_URL =  '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

api/filesDosyanız bir form-dataalana eklenmiş olarak adresine bir gönderi isteği gönderin file. Dosya /mediaklasöre yüklenecek ve id ve dosya adıyla birlikte bir db kaydı eklenecektir.


0

Django-rest-framework'te istek verileri Parsers.
http://www.django-rest-framework.org/api-guide/parsers/

Varsayılan olarak django-rest-framework çözümleyici sınıfını alır JSONParser. Verileri json olarak ayrıştıracaktır. bu nedenle dosyalar onunla ayrıştırılmayacaktır.
Dosyaların diğer verilerle birlikte ayrıştırılmasını istiyorsak, aşağıdaki ayrıştırıcı sınıflarından birini kullanmalıyız.

FormParser
MultiPartParser
FileUploadParser

DRF 3.8.2 güncel sürümü günü, varsayılan olarak ayrıştırmak olacak application/json, application/x-www-form-urlencodedve multipart/form-data.
Liquidki

0

Yardımcı olacağını umduğum yaklaşımlardan biri budur.

     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)

0

@ Nithin'in cevabını doğrudan DRF'nin mevcut serileştirici sistemiyle çalışmak için genelleştirebilir, belirli alanları ayrıştırmak için bir ayrıştırıcı sınıfı oluşturabilir ve bunlar daha sonra doğrudan standart DRF serileştiricilerine beslenir:

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

Bu şu şekilde kullanılır:

class MyFileViewSet(ModelViewSet):
    parser_classes = [gen_MultipartJsonParser(['tags', 'permissions'])]
    #                                           ^^^^^^^^^^^^^^^^^^^
    #                              Fields that need to be further JSON parsed
    ....
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.