Asked  4 Months ago    Answers:  5   Viewed   633 times

In django rest framework, I am able to upload single file using danialfarid/ng-file-upload

views.py:

class PhotoViewSet(viewsets.ModelViewSet):
    serializer_class = PhotoSerializer
    parser_classes = (MultiPartParser, FormParser,)
    queryset=Photo.objects.all()

    def perform_create(self, serializer):
        serializer.save(blogs=Blogs.objects.latest('created_at'),
                   image=self.request.data.get('image'))

serializers.py:

class PhotoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Photo

models.py:

class Photo(models.Model):
    blogs = models.ForeignKey(Blogs, related_name='blogs_img')
    image = models.ImageField(upload_to=content_file_name)

When I try to upload multiple file. I get in

chrome developer tools: Request Payload

------WebKitFormBoundaryjOsYUxPLKB1N69Zn
Content-Disposition: form-data; name="image[0]"; filename="datacable.jpg"
Content-Type: image/jpeg


------WebKitFormBoundaryjOsYUxPLKB1N69Zn
Content-Disposition: form-data; name="image[1]"; filename="datacable2.jpg"
Content-Type: image/jpeg

Response:

{"image":["No file was submitted."]}

I don't know how to write serializer for uploading multiple file.

 Answers

72

I manage to solve this issue and I hope it will help community

serializers.py:

class FileListSerializer ( serializers.Serializer ) :
    image = serializers.ListField(
                       child=serializers.FileField( max_length=100000,
                                         allow_empty_file=False,
                                         use_url=False )
                                )
    def create(self, validated_data):
        blogs=Blogs.objects.latest('created_at')
        image=validated_data.pop('image')
        for img in image:
            photo=Photo.objects.create(image=img,blogs=blogs,**validated_data)
        return photo

class PhotoSerializer(serializers.ModelSerializer):

    class Meta:
        model = Photo
        read_only_fields = ("blogs",)

views.py:

class PhotoViewSet(viewsets.ModelViewSet):
    serializer_class = FileListSerializer
    parser_classes = (MultiPartParser, FormParser,)
    queryset=Photo.objects.all()
Tuesday, June 29, 2021
 
nfechner
answered 4 Months ago
81

You can do what you are asking, and its your lucky day. I faced that problem when I first started working with django and oauth-toolkit.

The following is my implementation using django-rest-framework. It will register the user, authenticate and return an oauth response.

The thought is this: Using django models we save the new user using the proper serializers and models. In the same response, we create a new oauth token and return it to the user.

serializers.py

from rest_framework import serializers
import models
from django.utils.translation import gettext_lazy as _


class RegisterSerializer(serializers.ModelSerializer):
    confirm_password = serializers.CharField()

    def validate(self, data):
        try:
            user = models.User.objects.filter(username=data.get('username'))
            if len(user) > 0:
                raise serializers.ValidationError(_("Username already exists"))
        except models.User.DoesNotExist:
            pass

        if not data.get('password') or not data.get('confirm_password'):
            raise serializers.ValidationError(_("Empty Password"))

        if data.get('password') != data.get('confirm_password'):
            raise serializers.ValidationError(_("Mismatch"))

        return data

    class Meta:
        model = models.User
        fields = ('username', 'first_name', 'last_name', 'password', 'confirm_password', 'is_active')
        extra_kwargs = {'confirm_password': {'read_only': True}}

view.py

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, permissions
from oauth2_provider.settings import oauth2_settings
from braces.views import CsrfExemptMixin
from oauth2_provider.views.mixins import OAuthLibMixin

import json
import models
import serializers

from django.utils.decorators import method_decorator
from django.http import HttpResponse
from django.views.generic import View
from django.views.decorators.debug import sensitive_post_parameters
from django.utils.translation import gettext_lazy as _
from django.db import transaction


class UserRegister(CsrfExemptMixin, OAuthLibMixin, APIView):
    permission_classes = (permissions.AllowAny,)

    server_class = oauth2_settings.OAUTH2_SERVER_CLASS
    validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS
    oauthlib_backend_class = oauth2_settings.OAUTH2_BACKEND_CLASS

    def post(self, request):
        if request.auth is None:
            data = request.data
            data = data.dict()
            serializer = serializers.RegisterSerializer(data=data)
            if serializer.is_valid():
                try:
                    with transaction.atomic():
                        user = serializer.save()

                        url, headers, body, token_status = self.create_token_response(request)
                        if token_status != 200:
                            raise Exception(json.loads(body).get("error_description", ""))

                        return Response(json.loads(body), status=token_status)
                except Exception as e:
                    return Response(data={"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
            return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        return Response(status=status.HTTP_403_FORBIDDEN) 

urls.py

rom django.conf.urls import url
from oauth2_provider import views as oauth2_views

import views

urlpatterns = [
    url(r'^user/register/$', views.UserRegister.as_view()),
]
Tuesday, August 10, 2021
 
user3082821
answered 2 Months ago
85

I got a solution. I need to make myfile an array like this: myfile[] :)

Wednesday, August 11, 2021
 
Andrew
answered 2 Months ago
83

I solved my problem by modifying my class ContactFilter like this:

import django_filters
from .models import Contact

class ContactFilter(django_filters.FilterSet):
   class Meta:
        model = Contact
        fields = {
            'first_name': ['startswith'],
            'last_name': ['startswith'],
        }
        together = ['first_name', 'last_name']

And in my view I just had to do this :

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer
    filter_class = ContactFilter

My request url looks like :

http://localhost:8000/api/v1/contact/?first_name__contains=Cl&last_name__contains=Tes

But I still wonder if I can have something like this in Django

http://localhost:8000/api/v1/contacts/?first_name=Cl**&last_name=Tes**
Sunday, August 15, 2021
 
waylaidwanderer
answered 2 Months ago
44

Here is my code that incorporates including/excluding fields, as well as dynamically adjusting the depth. Adjust it to your taste. :)

class DynamicModelSerializer(serializers.ModelSerializer):
"""
A ModelSerializer that takes an additional `fields` argument that
controls which fields should be displayed, and takes in a "nested"
argument to return nested serializers
"""

def __init__(self, *args, **kwargs):
    fields = kwargs.pop("fields", None)
    exclude = kwargs.pop("exclude", None)
    nest = kwargs.pop("nest", None)

    if nest is not None:
        if nest == True:
            self.Meta.depth = 1

    super(DynamicModelSerializer, self).__init__(*args, **kwargs)

    if fields is not None:
        # Drop any fields that are not specified in the `fields` argument.
        allowed = set(fields)
        existing = set(self.fields.keys())
        for field_name in existing - allowed:
            self.fields.pop(field_name)

    if exclude is not None:
        for field_name in exclude:
            self.fields.pop(field_name)
Tuesday, September 21, 2021
 
Elxx
answered 4 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :