noob
noob

Reputation: 140

Upload image with DRF from react frontend

I want to upload image from react frontend. I tested the api from DRF browsable API, it worked as expected.

#views.py
class CreatePost(CreateAPIView):
    permission_classes = (permissions.AllowAny, )
    queryset = BlogPost.objects.all()
    serializer_class = BlogCreateSerializer

#serializers.py
class BlogCreateSerializer(serializers.ModelSerializer):

    class Meta:
        model = BlogPost
        fields = ('id', 'title', 'category', 'thumbnail',
                  'excerpt', 'content', 'author')

On the react side

  const onChange = (e) =>
setFormData({ ...formData, [e.target.name]: e.target.value });


<div className="form-group">
      <label htmlFor="exampleFormControlFile1">THUMBNAIL</label>
      <input
        type="file"
        className="form-control-file"
        name="thumbnail"
        value={thumbnail}
        onChange={(e) => onChange(e)}
        required
      />
    </div>



headers: {
  "Content-type": "multipart/form-data",
},

And as for errors: in console response JSON

detail  "Multipart form parse error - Invalid boundary in multipart: None"

in console request.payload

{"title":"dkjhksnc","category":"environment","thumbnail":"C:\\fakepath\\80dbf456adfc4e5499f86b04de37fad5.jpg","excerpt":"ewfewgrf ","content":"efewfewgw","author":"1"}

I am new to both DRF and react. Please see how can I upload "thumbnail" field for my blog posts.

If you need any other details please comment.

Upvotes: 2

Views: 1035

Answers (1)

ahmed osama
ahmed osama

Reputation: 61

On the front end:

function onImageSelected(e) {
  const formData = new FormData()

  // It probably won't work if the file name doesn't include the image extension especially if you're using ImageField in your django model
  formData.append('image', e.currentTarget.files[0], 'image.png')
  
  // I am using axios, you could use XMLHttpRequest if you want
  // You don't have to specify Content-Type headers yourself, they will be inferred from the data passed in.
 axios.post('your_endpoint', formData)
 .then((res)=> {// Success}).catch((err)=> {// Failure})

}

On the backend:

The default django rest framework configuration handles both json and form data, so you don't have to do anything.

Say that this is your endpoint:

@api_view(['POST'])
def my_view(request):
   s = MySerializer(request.data)
   s.is_valid(raise_exception=True)
   s.save()

That's it. You could use ImageField or FileField on your model to store the image. Note that it actually only stores the url and uploads your image to your storage backend whether it's the file system (default) or any other backend like amazon s3 or google cloud storage. Look django-storages library for more information.

The file system is only suitable for development. In order to use it, you need to set MEDIA_URL and MEDIA_ROOT in your settings file:

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

That's it. If you want to be able to preview the images through your browser during development, you need to add this to your urls.py as shown here

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
   # ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Upvotes: 2

Related Questions