0

My application is using django rest framework for the backend and react on the frontend.

I have a model Place which has several fields, one of which is a photo. I have a front end form that connects to the api endpoint to create a new Place model.

Whenever I submit the form through my react form (with the file included), the server responds with a 200 but does not actually save anything to the db. Whenever I submit the form without the file through my react app, it saves the other data successfully.

The weird thing is, I can get it to work without a problem using Postman, so my guess is the problem lies within the react component / HTML form.

Here is the react component with form:

import React, {useState, useContext, useRef} from "react";
import AuthContext from '../store/auth-context';

function NewPlaceForm(props) {

  const authCtx = useContext(AuthContext);

  const nameInputRef = useRef();
  const latInputRef = useRef();
  const longInputRef = useRef();
  const completedInputRef = useRef();
  const dateCompletedInputRef = useRef();
  const photoInputRef = useRef();
  const notesInputRef = useRef();
  const userId = localStorage.getItem('userId');

  const submitHandler = (event) => {
      event.preventDefault();
      const enteredName = nameInputRef.current.value;
      const enteredLat = latInputRef.current.value;
      const enteredLong = longInputRef.current.value;
      const enteredCompleted = completedInputRef.current.value;
      const enteredDateCompleted = dateCompletedInputRef.current.value;
      const enteredPhoto = photoInputRef.current.files;
      const enteredNotes = notesInputRef.current.value;


      let url = 'http://localhost:8000/api/create/';
      fetch(url, {
        method: 'POST',
        body: JSON.stringify({
          name: enteredName,
          lat: enteredLat,
          long: enteredLong,
          completed: enteredCompleted,
          dateCompleted: enteredDateCompleted,
          photo: enteredPhoto,
          notes: enteredNotes,
          user: userId
        }),
        headers:{
          Authorization: "Bearer " + authCtx.token
        }
      }
      )
      
      
     
  }

  return (
    <div>
      <h3>Add a new place</h3>
      <form onSubmit={submitHandler}>
        <label htmlFor="name">Name</label>
        <input name="name" type="text" ref={nameInputRef} required/>
        <br />
        <label htmlFor="latitude">Latitude</label>
        <input name="latitude" type="number" ref={latInputRef} required/>
        <br />
        <label htmlFor="longitude">Longitude</label>
        <input name="longitude" type="number" ref={longInputRef} required/>
        <br />
        <label htmlFor="completed">Completed</label>
        <input name="completed" type="checkbox" ref={completedInputRef}/>
        <br />
        <label htmlFor="date-completed">Date Completed</label>
        <input name="date-completed" type="date" ref={dateCompletedInputRef}/>
        <br />
        <label htmlFor="photo">Photo</label>
        <input name="photo" type="file" ref={photoInputRef}/>
        <br/>
        <label htmlFor="notes">Notes</label>
        <textarea name="notes" rows="2" cols="30" ref={notesInputRef}/>
      </form>
      <button type="button" onClick={submitHandler}>Add</button>
      <button onClick={props.onCancel}>Cancel</button>
    </div>
  );
}

export default NewPlaceForm;

API view:

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def createPlace(request):
    serializer = PlaceSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
    return Response(serializer.data)

Place model:

class Place(models.Model):
    name = models.CharField(max_length=200)
    lat = models.FloatField()
    long = models.FloatField()
    completed = models.BooleanField(default=False)
    date_completed = models.DateField(auto_now=False, blank=True, null=True)
    photo = models.ImageField(upload_to='img/', blank=True)
    notes = models.TextField(max_length=1000, blank=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

Serializer:

class PlaceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Place
        fields = '__all__'

If I console.log(enteredPhoto) in the Fetch function, it logs the file object with the name and everything. Also if I print(request.data) I get the following response:

{'name': '717', 'lat': '7', 'long': '7', 'completed': 'on', 'dateCompleted': '', 'photo': {'0': {}}, 'notes': '', 'user': '1'}
c_the_b
  • 63
  • 6
  • I don't think you can send a file like that in a request body that's formatted as JSON. Maybe this post will help: https://stackoverflow.com/questions/4083702/posting-a-file-and-associated-data-to-a-restful-webservice-preferably-as-json – Calvin Jun 14 '21 at 00:46

0 Answers0