[Django]-How to save file in django rest

5πŸ‘

An example using rest_framework.parsers ==>> FileUploadParser:

url.py:

urlpatterns = +[
    url(r'^docs/$', views.DocumentView.as_view(), name='docs'),
]

models.py

class Document(models.Model):
    DOC_CATEGORY = (
        ('profile_pic', 'Profile_Picture'),
    )

    class Meta:
        ordering = ['uploaded_at']

    uploaded_at = models.DateTimeField(auto_now_add=True)
    file = models.FileField(blank=False, null=False)
    # description
    remark = models.CharField(max_length=200, blank=True, null=True)
    user = models.ForeignKey(User, blank=True, on_delete=models.DO_NOTHING,)
    category = models.CharField(
        'Document category',
        max_length=64,
        choices=DOC_CATEGORY,
        default='profile_pic')

    def __str__(self):
        return self.file.name

serializers.py

class DocumentSerializer(serializers.ModelSerializer):
    class Meta():
        model = Document
        fields = ('file', 'remark', 'uploaded_at', 'user', 'category')

and last views.py:

from rest_framework.parsers import FileUploadParser

class DocumentView(APIView):

    http_method_names = ['get', 'post']
    model = Document
    # fields = ['upload', ]
    success_url = reverse_lazy('/')
    parser_class = (FileUploadParser,)
    # permission_classes = [DocumentViewPerm, ]
    # allow any for the example!!!
    permission_classes = [AllowAny, ]

    def get_object(self, pk):

         return serializers.serialize(
              'json', list(Document.objects.filter(pk=pk))
                )
    def get(self, request, pk=None, format=None):
        category = request.query_params.get('category', None)
        if request.query_params.get('pk'):
            return HttpResponse(
                self.get_object(pk=request.query_params.get('pk'),
                content_type="application/json")


        return HttpResponse(self.get_object(request.user.pk), 
            content_type="application/json")

    def post(self, request, *args, **kwargs):
        file_serializer = DocumentSerializer(data=request.data)
        ########################################################
        # when uploading keep these headers- no content type !!!

        # headers = {'Authorization': '{}'.format(token), 'Accept': 
        # 'application/json'}
        ########################################################
        if file_serializer.is_valid():
            file_serializer.save(user=self.request.user)
            # save all fields 
            # remark  # category 
            remark = request.data.get('remark')
            category = request.data.get('category')

            return Response(file_serializer.data, 
                status=status.HTTP_201_CREATED)

        else:
            return Response(file_serializer.errors, 
                status=status.HTTP_400_BAD_REQUEST)

#

EXAMPLE upload a file, open python cmd line

import requests, json
# no content type in headers !!!

headers = {'Accept': 'application/json',
 'Authorization': "TOKEN"}
with open('pathtofile', 'rb') as f:
  r = requests.post('http://MachineIP/docs/', files={'file': f}, data={'remark': 'my remark'}, headers=headers)
πŸ‘€Ohad the Lad

0πŸ‘

You do not have to write your custom code. Using ModelSerializer, you can achieve what you want.

class TicketFilesSerializer(serializer.ModelSerializer):
    class Meta:
        model = TicketFiles
        fields = '__all__'

You can add other fields that you want according to your requirement.

In your API view,

class YourView(generics.GenericApiView):
    serializer_class = TicketFilesSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(request.data)
        if serializer.is_valid():
            serializer.save()

You have to send data in multipart format.

Leave a comment