skip to Main Content

I am trying to upload an image with other form data using Django & React.

I get 400 Bad Request.

First API should create a new product without an image then the second one will edit the product and add an image to it.

when i create a product in the client side ,I get 200 status to the first API and 400 to the second one.

Using FileReader allowed the browser to read the url of the image.

Here is My code:

React

export default function Add(){

    let [formData , setFormData] = useState({namee: '',price: ''})
    let [files , setFiles] = useState(null)
   
  

    const handleInputChange = (event) => {
        const { name , value } = event.target
        setFormData({...formData, [name] : value})
    }

    const handleImageChange = (event) => {

      const file = event.target.files[0]
      const reader = new FileReader()
      reader.addEventListener("load", function() {
        console.log(reader.result)
        setFiles(reader.result)
      })
      reader.readAsDataURL(file)
      
    }


    const handleSubmit = (event) => {
      
      event.preventDefault()
      const { namee, price } = formData
      const formDataObj1 = new FormData()
      const formDataObj2 = new FormData()
      formDataObj1.append('namee', namee)
      formDataObj1.append('price', price)
      formDataObj2.append('image', files)
      
      if(files){
        fetch('http://127.0.0.1:8000/add' , 
            {
                method: "POST",
                body: formDataObj1,
            }
        )
            .then(response => {
                if(response.ok){
                  
                   fetch('http://127.0.0.1:8000/addimage', 
                   {
                    method: "PUT",
                    body: formDataObj2,
                   })
                   .then(response => {
                    console.log(response)
                    if(response.ok){
                      alert('Your Product has been added :)')
                    }
                    else{
                      console.error('Form submission failed.')
                  }
                   })
                   .catch(error => {
                      console.log(error)
                   })
                }
                else{
                    console.error('Form submission failed.')
                }
            })
                .catch(error => {
                    console.log('Form submission failed.' , error)
                })
    }
    else{
      console.log('files is empty')
    }
  }

    const imgStyle = {
        marginBottom: '10px'
    }

    return (
        <div className="c3">
        <div id="info" className="center">
          <h1>Product</h1>
          <form onSubmit={handleSubmit} >
            <div className="txt_field">
              <input type="text" name="namee" value={formData.namee} onChange={handleInputChange} required/>
              <span></span>
              <label>Name</label>
            </div>
            <div className="txt_field">
              <input type="number" name="price" value={formData.price} onChange={handleInputChange} required/>
              <span></span>
              <label>Price</label> 
            </div>
            <div style={imgStyle}>
              <input type="file" name="image" onChange={handleImageChange}  required/>
              <span></span>
            </div>
            <input  type="submit" value="Confirm" className="ss"/>
          </form>
        </div>
      </div>
    )

}

Django

class AddProduct(generics.CreateAPIView):


    serializer_class = ProductSerializer

    def post(self , request , format=None):
        name = request.data['namee']
        price = request.data['price']
        Product.objects.create(name=name, price=price)
        return Response('product successfuly added', status=status.HTTP_200_OK)


class AddProductImage(APIView):

    serializer_class = AddImageProSerializer
    parser_classes = ( MultiPartParser, parsers.JSONParser)   

    def put(self , request ):
        product = Product.objects.last()
        serializer = AddImageProSerializer(data=request.data , instance = product)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_200_OK)

2

Answers


  1. 1. Set up Django Backend:
    
    Assuming you have Django already installed, follow these steps:
    
    Step 1: Create a new Django project and app if you haven't already:
    
    bash
    django-admin startproject project_name
    cd project_name
    django-admin startapp app_name
    Step 2: Define your model to handle image uploads. In models.py:
    
    python
    # app_name/models.py
    from django.db import models
    
    class ImageModel(models.Model):
        image = models.ImageField(upload_to='images/')
        # Add any other fields you need for your image model
    Step 3: Make migrations and migrate to create the database table:
    
    bash
    python manage.py makemigrations
    python manage.py migrate
    Step 4: Set up a Django view to handle image uploads in views.py:
    
    python
    # app_name/views.py
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.parsers import FileUploadParser
    from rest_framework import status
    
    class ImageView(APIView):
        parser_classes = (FileUploadParser,)
    
        def post(self, request, *args, **kwargs):
            image_serializer = ImageSerializer(data=request.data)
    
            if image_serializer.is_valid():
                image_serializer.save()
                return Response(image_serializer.data, status=status.HTTP_201_CREATED)
            else:
                return Response(image_serializer.errors, status=status.HTTP_400_BAD_REQUEST)`enter code here`
    Step 5: Define a serializer for the image model in serializers.py:
    
    python
    # app_name/serializers.py
    from rest_framework import serializers
    from .models import ImageModel
    
    class ImageSerializer(serializers.ModelSerializer):
        class Meta:
            model = ImageModel
            fields = ('image',)
    Step 6: Configure Django URLs to handle the image upload API:
    
    python
    # app_name/urls.py
    from django.urls import path
    from .views import ImageView
    
    urlpatterns = [
        path('upload/', ImageView.as_view(), name='image-upload'),
    ]
    2. Set up React Frontend:
    
    Step 1: Create a new React project if you haven't already:
    
    bash
    npx create-react-app react_app_name
    cd react_app_name
    Step 2: Install the necessary dependencies:
    
    bash
    npm install axios react-dropzone
    Step 3: Create a component to handle the image upload in React, ImageUpload.js:
    
    jsx
    import React, { useState } from 'react';
    import axios from 'axios';
    import Dropzone from 'react-dropzone';
    
    const ImageUpload = () => {
      const [selectedImage, setSelectedImage] = useState(null);
    
      const handleImageUpload = async () => {
        const formData = new FormData();
        formData.append('image', selectedImage);
    
        try {
          await axios.post('http://your_django_backend/upload/', formData, {
            headers: {
              'Content-Type': 'multipart/form-data',
            },
          });
          alert('Image uploaded successfully!');
        } catch (error) {
          console.error('Error uploading image:', error);
        }
      };
    
      return (
        <div>
          <h1>Image Upload</h1>
          <Dropzone onDrop={(acceptedFiles) => setSelectedImage(acceptedFiles[0])}>
            {({ getRootProps, getInputProps }) => (
              <div className="dropzone" {...getRootProps()}>
                <input {...getInputProps()} />
                {selectedImage ? (
                  <img src={URL.createObjectURL(selectedImage)} alt="Selected" />
                ) : (
                  <p>Drag and drop an image here or click to select an image.</p>
                )}
              </div>
            )}
          </Dropzone>
          <button onClick={handleImageUpload} disabled={!selectedImage}>
            Upload Image
          </button>
        </div>
      );
    };
    
    export default ImageUpload;
    Step 4: Use the ImageUpload component in your main App.js file:
    
    jsx
    import React from 'react';
    import ImageUpload from './ImageUpload';
    
    function App() {
      return (
        <div className="App">
          <ImageUpload />
        </div>
      );
    }
    
    export default App;
    3. Run the Project:
    
    Step 1: Start the Django development server:
    
    bash
    python manage.py runserver
    Step 2: Start the React development server:
    
    bash
    npm start
    
    Login or Signup to reply.
  2. Rather than develop and debug both sides at once I have found it helpful to use something like httpie to test the Django API. This allows you to confirm that it is responding as expected. Once that is working you can use the settings from httpie in your react app.

    I have mainly used axios (rather than fetch) with Django model viewsets (rather than an api view). In that case if your model has a FileField or ImageField Django will simply "handle" the upload by default.

    Django is expecting a multipart upload since you are sending form data and a file. This needs to be set in the headers on the client side (fetch or axios) which I notice you are not doing. You could start by fixing that. If that doesn’t work and you want more help, consider posting the pertinent info from urls.py, models.py, and serializers.py in addition to the views.py info you have already posted.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search