#reactjs #django #redux #django-rest-framework
#reactjs #django #redux #django-rest-framework
Вопрос:
Я пытаюсь добавить файлы изображений в массив изображений с помощью React, но получаю пустой массив изображений. Мой бэкэнд написан на Django. Он работает нормально, когда я использую postman для вставки файлов изображений, но я получаю пустой массив при использовании react.
AddNewStudent.js файл
const AddNewStudent = () => {
const [Name, setName]= useState('')
const [Enrollment_No, setEnrollmentNo]= useState('')
const [Registration_No, setRegistrationNo]= useState('')
const [Semester, setSemester]= useState('')
const [Year, setYear]= useState('')
const [Course_Name, setCourseName]= useState('')
const [Course_Code, setCourseCode]= useState('')
const [studentImages, setStudentImages]= useState([])
const dispatch= useDispatch()
const submitForm= (e) => {
e.preventDefault()
const images=[]
for (let image of studentImages){
images.push({
image
})
}
console.log(images)
const student={
Name,
Enrollment_No,
Registration_No,
Semester,
Year,
Course_Name,
Course_Code,
images
}
console.log(student)
dispatch(addStudent(student))
}
const handleStudentImages = (e) => {
setStudentImages([
...studentImages,
e.target.files[0]
])
}
return (
<CCard>
<CCardHeader>
Add New Student
</CCardHeader>
<CCardBody>
<CForm action="" method="post" onSubmit={submitForm}>
<CFormGroup>
<CLabel htmlFor="nf-name">Name</CLabel>
<CInput type="text" id="nf-name" name="nf-name" placeholder="Name" autoComplete="name" onChange={(e) => setName(e.target.value)}/>
</CFormGroup>
<CFormGroup row className="my-0">
<CCol xs="6">
<CFormGroup>
<CLabel htmlFor="nf-enrollmentno">Enrollment No</CLabel>
<CInput type="text" id="nf-enrollmentno" name="nf-enrollmentno" placeholder="Enrollment Number" autoComplete="enrollment_no" onChange={(e) => setEnrollmentNo(e.target.value)}/>
</CFormGroup>
</CCol>
<CCol xs="6">
<CFormGroup>
<CLabel htmlFor="nf-registrationno">Registration No</CLabel>
<CInput type="text" id="nf-registrationno" name="nf-registrationno" placeholder="Registration Number" autoComplete="registration_no" onChange={(e) => setRegistrationNo(e.target.value)}/>
</CFormGroup>
</CCol>
</CFormGroup>
<CFormGroup row className="my-0">
<CCol xs="6">
<CFormGroup>
<CLabel htmlFor="select">Select Semester</CLabel>
<CSelect custom name="select" id="select" onChange={(e) => setSemester(e.target.value)}>
<option value="0">Please select</option>
<option value="1">Semester 1</option>
<option value="2">Semester 2</option>
<option value="3">Semester 3</option>
<option value="4">Semester 4</option>
<option value="5">Semester 5</option>
<option value="6">Semester 6</option>
<option value="7">Semester 7</option>
<option value="8">Semester 8</option>
</CSelect>
</CFormGroup>
</CCol>
<CCol xs="6">
<CFormGroup>
<CLabel htmlFor="select">Select Year</CLabel>
<CSelect custom name="select" id="select" onChange={(e) => setYear(e.target.value)}>
<option value="0">Please select</option>
<option value="Fall 2020">Fall 2020</option>
<option value="Spring 2021">Spring 2021</option>
<option value="Fall 2021">Fall 2021</option>
<option value="Spring 2022">Spring 2022</option>
</CSelect>
</CFormGroup>
</CCol>
</CFormGroup>
<CFormGroup row className="my-0">
<CCol xs="6">
<CFormGroup>
<CLabel htmlFor="select">Select Course Name</CLabel>
<CSelect custom name="select" id="select" onChange={(e) => setCourseName(e.target.value)}>
<option value="0">Please select</option>
<option value="DCN">DCN</option>
<option value="OOP">OOP</option>
<option value="DBMS">DBMS</option>
<option value="DSA">DSA</option>
</CSelect>
</CFormGroup>
</CCol>
<CCol xs="6">
<CFormGroup>
<CLabel htmlFor="select">Select Course Code</CLabel>
<CSelect custom name="select" id="select" onChange={(e) => setCourseCode(e.target.value)}>
<option value="0">Please select</option>
<option value="D1-101">D1-101</option>
<option value="ST-203">ST-203</option>
<option value="AD-567">AD-567</option>
<option value="TU-689">TU-689</option>
</CSelect>
</CFormGroup>
</CCol>
</CFormGroup>
<CFormGroup row>
<CCol md="3">
<CLabel>Add Images</CLabel>
</CCol>
<CCol xs="12" md="9">
<CInputFile
id="file-multiple-input"
name="file-multiple-input"
multiple
custom
onChange={handleStudentImages}
/>
<CLabel htmlFor="file-multiple-input" variant="custom-file">
{
studentImages.length > 0 ? studentImages.map(img => {
return(
<span style={{paddingRight: 10}}>{img.name}</span>
)
}) : 'Add files...'
}
</CLabel>
</CCol>
</CFormGroup>
<CCardFooter>
<CButton type="submit" size="sm" color="primary"><CIcon name="cil-scrubber" /> Submit</CButton> <CButton type="reset" size="sm" color="danger"><CIcon name="cil-ban" /> Reset</CButton>
</CCardFooter>
</CForm>
</CCardBody>
</CCard>
)
}
export default AddNewStudent
actions student.js
export const addStudent = (form) => {
return async (dispatch) => {
dispatch({
type: studentConstants.ADD_STUDENTS_REQUEST
})
try{
const res= await axios.post(`/student/`, {
...form
})
console.log(res.data)
}
catch(error){
console.log(error.response.data)
}
}
}
Я получаю изображения в виде файлов, когда печатаю student, но когда я передаю student в actions, массив изображений пуст
Комментарии:
1. Я думаю, вам может понадобиться упорядочить ваш
form
объект данных в формате JSON в вашемaddStudent
action creator.2. привет, когда я это делаю, я получаю ошибки. {Name: Array(1), Enrollment_No: Array(1), Registration_No: Array(1), Year: Array(1), Course_Name: Array(1), …} Course_Code: [«Это поле обязательно».] Course_Name: [«Это поле обязательно».]Enrollment_No: [«Это поле обязательно».] Имя: [«Это поле обязательно».] Registration_No: [«Это поле обязательно».] Год: [«Это поле обязательно».] прото : объект e
3. Облом, извините. Вы подтвердили, что ваше
studentImages
состояние обновлено? Для этого вы можете использовать react-dev-tools. Когда действие отправляется, какова ценностьform
объекта? Этоform.images
то, чего вы ожидаете? Вы проверили вкладку network, чтобы убедиться, что ваш запрос POST верен? Вы сравнивали этот запрос с тем, который был сделан в Postman?4. Возможно, вам потребуется установить
multipart/form-data
в качестве content-type (заголовок в запросе)5. Большое вам спасибо @NadiaChibrikova. Наконец-то работает, я установил заголовки в соответствии с типом содержимого в моем запросе postman, и теперь это работает как шарм!
Ответ №1:
итак, я наконец-то заработал. что я сделал, так это изменил объект student на данные формы
const form= new FormData();
form.append('Name', Name)
form.append('Enrollment_No', Enrollment_No);
form.append('Registration_No', Registration_No);
form.append('Semester', Semester);
form.append('Year', Year);
form.append('Course_Name', Course_Name);
form.append('Course_Code', Course_Code);
for (let image of studentImages){
form.append(`image_${image.name}`, image)
}
а затем добавил хедеры содержимого в действие addStudent
const headers= {
"Content-Type": "multipart/form-data; boundary=<calculated when request is sent>"
}
try{
const res= await axios.post(`/student/`, form, { headers: headers })
console.log(res.data)
}
и это работает!