Django Rest Framework carga el archivo a un método

Así que he estado tratando de cargar un archivo a un método usando DRF sin suerte hasta ahora.

Pude subir a un ModelViewSet usando (FormParser, MultiPartParser,) sin problemas, pero realmente necesito usarlo en algo como esto http://localhost:8000/api/v1/women/{pk}/upload_avatar/ donde primero quiero filtrar a la mujer por id y subirla a su avatar (que es una clave externa para un modelo multimedia). Intenté usar una biblioteca de recursos anidada sin suerte.

Hasta ahora tengo en mi modelviewset:

 class WomenNativePassportViewSet(viewsets.ModelViewSet): queryset = Women.objects.all() serializer_class = WomenNativePassportSerializer authentication_classes = (NoAuthentication,) permission_classes = (AllowAny,) parser_classes = (FormParser, MultiPartParser,) @detail_route( methods=['post', 'put', 'patch', 'get'], permission_classes=[AllowAny], authentication_classes=[NoAuthentication], serializer_class=MultimediaSerializer, parser_classes=(FormParser, MultiPartParser,) ) def upload_avatar(self, request, pk=None, *args, **kwargs): if 'POST' in request._method or 'PATCH' in request._method: # Write code to save the file?? else: multimedia = Multimedia.objects.filter(user_profiles_avatares__pk=pk) page = self.paginate_queryset(multimedia) serializer = self.get_pagination_serializer(page) return Response(serializer.data) 

Mis modelos:

 class Women(models.Model): user = models.OneToOneField(settings.AUTH_USER_MODEL) avatar = models.ForeignKey( 'core.Multimedia', blank=True, null=True, related_name='user_profiles_avatares' ) class Multimedia(models.Model): file = models.FileField(upload_to=upload_to, null=True, blank=True) thumbnail = models.FileField(upload_to=upload_to, null=True, blank=True) 

Básicamente, quiero saber si este es el camino correcto que estoy tomando, y si es así, ¿cómo puedo guardar correctamente el archivo cargado en el modelo?

Aquí hay un código de lo que hice para superar este problema. Aunque la respuesta de Kevin Brown probablemente funciona, encuentro que mi código es un enfoque “más fácil”:

  @detail_route( methods=['post', 'put', 'patch', 'get'], permission_classes=[AllowAny], authentication_classes=[NoAuthentication], serializer_class=MultimediaSerializer, parser_classes=(FormParser, MultiPartParser,) ) def upload_avatar(self, request, pk=None): # Because we are using nested resources this was the only way i found to # upload a file. Maybe there is a better way if request.method in ['PATCH', 'POST']: avatar = request.FILES.get('avatar') if not avatar: return Response(status=404) try: woman = WomenNativePassport.objects.get(pk=pk) except WomenNativePassport.DoesNotExist: return Response(status=404) else: request.FILES['thumbnail'] = request.FILES['avatar'] serializer = AvatarSerializer( data=request.DATA, files=request.FILES ) if serializer.is_valid(): woman.avatar.thumbnail.save(str(avatar), File(avatar)) return Response(status=204) else: return Response(status=404) else: multimedia = Multimedia.objects.filter(user_profiles_avatares__pk=pk) page = self.paginate_queryset(multimedia) serializer = self.get_pagination_serializer(page) return Response(serializer.data) # serializer class AvatarSerializer(serializers.Serializer): thumbnail = serializers.ImageField() 

Cualquier archivo cargado debe estar disponible en la request.FILES . request.FILES , un diccionario codificado por el campo que se usó al cargar. Una vez que tenga el archivo, es cuestión de manejarlo de manera similar a cualquier otro archivo cargado en Django .

Si puede, usaría un segundo serializador que envuelve el modelo Multimedia para que la validación de la imagen y el guardado se puedan realizar automáticamente a través del marco Django REST. Hay un ImageField que validará automáticamente la imagen mediante una Pillow que puede usar en el serializador.