42

I have model Product:

def productFile(instance, filename):
    return '/'.join( ['products', str(instance.id), filename] )

class Product(models.Model):
    ...

    image = models.ImageField(
        upload_to=productFile,
        max_length=254, blank=True, null=True
    )
    ...

Then I have serializer:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = (
            ...
            'image',
            ...
        )

And then I have views:

class ProductViewSet(BaseViewSet, viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

How I can upload image with Postman? What is the best practices to upload image to model? Thank you.

5
  • 2
    Remove the paranthesis, serializer_class = ProductSerializer.. If you are using ModelViewSet, then you don't need to write anything more... ViewSet would handle pretty much everything for you. Commented Aug 8, 2017 at 9:51
  • Ok, thanks, and how can I upload image with postman, or some Ajax request? Commented Aug 8, 2017 at 10:47
  • When I use that in my model, I get a ValueError("Cannot serialize function: lambda") Commented Dec 18, 2018 at 6:00
  • @Rony Azrak, I'he just updated the question with a solution that works. use method productFile Commented Dec 18, 2018 at 16:12
  • Can you send me your code to post data in model with image file I'm wondering for it..my code show me bad request 400 http://.... Commented Aug 22, 2020 at 7:14

4 Answers 4

34

you can create separate endpoint for uploading images, it would be like that:

class ProductViewSet(BaseViewSet, viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

    @detail_route(methods=['post'])
    def upload_docs(request):
        try:
            file = request.data['file']
        except KeyError:
            raise ParseError('Request has no resource file attached')
        product = Product.objects.create(image=file, ....)

you can go around that solution

-- update: this's how to upload from postman enter image description here

Sign up to request clarification or add additional context in comments.

6 Comments

you can upload using postman by select form-data on body and select type to file and click on choose file, write file on key field see the update above.
Thank you! Can I have url with method "PUT" like /api/products/33/upload_docs ?
yes you can of course but I didn't check if you can upload with PUT method or not
hm, I'm, just tried your solution, but I got error {"detail":"Missing filename. Request should include a Content-Disposition header with a filename parameter."} . Do you know how can I "turn off" this requirement? Once more Thank you! :)
problem was with parser, I used FileUploadParser instead of MultiPartParser :) Thank you!
|
24

I lately start Django and have same problem for upload image.

All steps that i done

  1. Install Pillow for using ImageField

    pip install Pillow
    
  2. In Settings.py add these lines

    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    MEDIA_URL = '/media/' # 'http://myhost:port/media/'
    
  3. Use ImageField in model.py (create nameFile function for create folder and name of file)

    def upload_to(instance, filename):
        return '/'.join(['images', str(instance.name), filename])
    
    class UploadImageTest(models.Model):
        name = models.CharField(max_length=100)
        image = models.ImageField(upload_to=upload_to, blank=True, null=True)
    
  4. serializer.py

    class ImageSerializer(serializers.ModelSerializer):
        class Meta:
            model = UploadImageTest
            fields = ('name', 'image')
    
  5. views.py

    class ImageViewSet(ListAPIView):
        queryset = UploadImageTest.objects.all()
        serializer_class = ImageSerializer
    
        def post(self, request, *args, **kwargs):
            file = request.data['file']
            image = UploadImageTest.objects.create(image=file)
            return HttpResponse(json.dumps({'message': "Uploaded"}), status=200)
    
  6. urls.py: add this line

    path('upload/', views.ImageViewSet.as_view(), name='upload'),
    
  7. admin.py: add this line (for check in admin)

    admin.site.register(UploadImageTest)
    
  8. in terminal

    python manage.py makemigrations
    python manage.py migrate
    

2 Comments

Have you tried to use MultiPartParser in views? Also I would recommend you to make new endpoint to 'upload_image' in ImageViewSet
can you tell how to update this in request.
4

models.py

from django.db import models

class ImageUpload(models.Model):
    title = models.CharField(max_length=50)
    images = models.ImageField('images')

serializers.py

from rest_framework import serializers
from .models import ImageUpload

class ImageUploadSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = ImageUpload
        fields= (
            'title',
            'images'
        )

views.py

from rest_framework import viewsets
from .models import ImageUpload
from .serializers import ImageUploadSerializer

class ImageUploadViewSet(viewsets.ModelViewSet):
    queryset = ImageUpload.objects.all()
    serializer_class = ImageUploadSerializer

urls.py

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter()
router.register(r'imageupload', views.ImageUploadViewSet)

urlpatterns = [
    path('imageupload', include(router.urls)),
]

Comments

1

this worked for me

class UserAvatarUpload(ListAPIView):
    
    parser_classes = [MultiPartParser, FormParser]
    serializer_class = ImageSerializer

    def post(self, request, *args, **kwargs):
        username = request.data['username']
        file = request.data['image']
        user = MyModel.objects.get(username=username)
        user.image = file
        user.save()
        return Response("Image updated!", status=status.HTTP_200_OK)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.