Django Rest and Dropzone React "The submitted data was not a file. Check the encoding type on the form."

72 Views Asked by At

I've got a react frontend with django backend trying to upload some images to django api enpoint I have 1 model in django but i want to first upload an image and then submit the rest of the data, the issue is when i try to upload the photos i get an error response photos [ "The submitted data was not a file. Check the encoding type on the form." ] I am using Dropzone to upload photos by the way Here is the react component handling uplaod

function ImageUploader() {
const [fileNames, setFileNames] = useState([]);

const handleDrop = async (acceptedFiles) => {
  try {
    // Create a new FormData object to send files
    const formData = new FormData();

    acceptedFiles.forEach((file) => {
      // Append each file to the FormData object
      formData.append('photos', file);
    });

    // Make a POST request to your photo upload endpoint
    //axios.defaults.headers.post['Content-Type'] = 'multipart/form-data';
    const response = await axios.post('http://localhost:8000/api/quotes/create/', formData, {
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'multipart/form-data',
      },
    });

    // Handle the response (e.g., show success message)
    console.log('Upload successful:', response.data.message);


    // Update the list of file names for display
    setFileNames(acceptedFiles.map((file) => file.name));
  } catch (error) {
    console.error('Upload failed:', error);
  }
};

  return (
    <div className="App">
      <Dropzone
        onDrop={handleDrop}
        accept={{ mimeType: ["image/jpeg", "image/png"] }}
        minSize={1024}
        maxSize={3072000}
      >

Then in django i have this view

class QuoteCreateAPIView(APIView):
def post(self, request, format=None):
    # Determine the current stage based on the presence of 'photos' field
    if 'photos' in request.data:
        # Stage 1: Upload Photos
        serializer = QuoteSerializer(data={'photos': request.FILES.getlist('photos')}, partial=True)
    else:
        # Stage 2: Submit Remaining Data
        serializer = QuoteSerializer(data=request.data, partial=True)

    if serializer.is_valid():
        # Check if 'photos' are being submitted in Stage 2, and update the 'photos' field accordingly
        if 'photos' not in serializer.validated_data:
            serializer.validated_data['photos'] = Quote.objects.get(pk=request.data['quote_id']).photos

        # Create or update the Quote instance
        try:
            quote_id = request.data.get('quote_id')
            if quote_id:
                quote = Quote.objects.get(pk=quote_id)
                serializer.update(quote, serializer.validated_data)
            else:
                serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        except Quote.DoesNotExist:
            return Response({'message': 'Quote not found'}, status=status.HTTP_404_NOT_FOUND)

    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Quote model

class Quote(models.Model):
quote_id = models.CharField(max_length=10, unique=True, default=get_unique_quote_id)
name = models.CharField(max_length=255)
phone = models.CharField(max_length=255)
email = models.EmailField(max_length=255)
# area = models.CharField(max_length=255)

make = models.ForeignKey(CarMake, on_delete=models.CASCADE, null=True) #
model = models.ForeignKey(CarModel, on_delete=models.CASCADE, null=True) #
variant = models.ForeignKey(ModelVariant, on_delete=models.CASCADE, null=True)
year = models.IntegerField(default=0) #
price = models.IntegerField(default=0) #
mileage = models.IntegerField(default=0) #
fuel = models.CharField(max_length=255, default='') #
transmission = models.CharField(max_length=255, default='') #

papers = models.CharField(max_length=3, default='') #
runner = models.CharField(max_length=3, default='') #
smashed = models.CharField(max_length=3, default='') #
financed = models.CharField(max_length=3, default='') # 
warranty = models.CharField(max_length=3, default='') #

condition = models.CharField(max_length=255, default='') #
comments = models.TextField(max_length=1000, default='') #
photos = models.ImageField(upload_to='photos/', ) #

date_time = models.DateTimeField(auto_now_add=True, null=True)


def __str__(self):
    return '%s' %(self.name)

And a serializer

class QuoteSerializer(serializers.ModelSerializer):
make = serializers.CharField()
model = serializers.CharField()
variant = serializers.CharField(required=False)

class Meta:
    model = Quote
    fields = '__all__'
    extra_kwargs = {
        'quote_id': {'required': False},
        'name': {'required': False},
        'phone': {'required': False},
        'email': {'required': False},
        'make': {'required': False},
        'model': {'required': False},
        'variant': {'required': False},

        'year': {'required': False},
        'price': {'required': False},
        'milage': {'required': False},
        'fuel': {'required': False},
        'transmission': {'required': False},
        'papers': {'required': False},
        'runner': {'required': False},
        'smashed': {'required': False},
        'financed': {'required': False},
        'warranty': {'required': False},
        'condition': {'required': False},
        'comments': {'required': False},
    }

def create(self, validated_data):
    make_name = validated_data.pop('make')
    model_name = validated_data.pop('model')
    variant_name = validated_data.pop('variant', None)

    make, _ = CarMake.objects.get_or_create(make=make_name)
    model, _ = CarModel.objects.get_or_create(model=model_name, make=make)
    variant, _ = ModelVariant.objects.get_or_create(variant=variant_name, make=make, model=model)
    quote = Quote.objects.create(make=make, model=model, variant=variant, **validated_data)
    return quote

The photos i am testing with are definitely fine in Network requests i am seeing this Content-Disposition: form-data; name="photos"; filename="bmw116i.jpeg" Content-Type: image/jpeg

and i printed requests.data in the view function which seems to return this

<QueryDict: {'photos': [<InMemoryUploadedFile: bmw116i.jpeg (image/jpeg)>]}>

0

There are 0 best solutions below