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'}