skip to Main Content

I’m trying to make simple blog app using django as a backend and react. I’m worikng on making post function. I didn’t have any problem with making simple post with title and description but they have shown up when I tried to add possibility of adding picture to a post.

thats post model:

class Post(models.Model):
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )
    title = models.CharField(max_length=200, default="no title")
    text = models.CharField(max_length=500)
    image = models.FileField(upload_to=getImageURL, blank=True, default="no-image.png")
    posted = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    

api view

@api_view(['POST'])
def MakePost(request):
    if request.method == 'POST':
        serializer = PostSerializer(data = request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

and my component

export default function MakePost(){
    
    const [userID, setUserID] = useState();
    const [text, setText] = useState('');
    const [title, setTitle] = useState('');
    const [image, setImage] = useState();
    const [username, setUsername] = useState(localStorage.username);
    
(...getting user ID)
    
    
    const fileSelectedHandler = async event => {
        setImage(event.target.files[0]);
        console.log(event.target.files[0]);
    }
    
    const submit = async e => {
            
        e.preventDefault();     
        
        const requestOptions = {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({author: userID, text: text, title: title, image: image})
        }
        
        fetch('http://localhost:8000/api/make-post/', requestOptions)
        .then(response => {
            console.log(response)
            if(response.ok){
                return response.json();
            }
        })
        .catch(error => {
            console.log(error)
        })
    }
    

    
    return(
        <div className="Auth-form-container mx-auto w-50 mt-5">
            <form className="Auth-form" onSubmit={submit} method="POST" encType="multipart/form-data">
                <div className="Auth-form-content">
                <h3 className="Auth-form-title">Make new Post</h3>
                <div className="form-group mt-3">
                    <label>Title</label>
                      <input className="form-control mt-1" 
                        placeholder="Enter text" 
                        name='postDescription'  
                        type='text' value={title}
                        required 
                        onChange={e => setTitle(e.target.value)}/>
                  <label>Description</label>
                  <input className="form-control mt-1" 
                    placeholder="Enter text" 
                    name='postDescription'  
                    type='text' value={text}
                    required 
                    onChange={e => setText(e.target.value)}/>
                </div>
                
                <Form.Group controlId="formFile" className="mb-3">
                    <Form.Label>Image</Form.Label>
                    <Form.Control type="file" onChange={fileSelectedHandler} />        
                </Form.Group>
                
                <div className="d-grid gap-2 mt-3">
                  <button onClick={submit} className="btn btn-primary">Post</button>
                </div>
                </div>
           
            </form>
            
         </div>
    )
}

How should I approach to that case ? Am I passing image in correct way ? (probably no)

3

Answers


  1. Chosen as BEST ANSWER

    I got rid of

                headers: {
                    'Content-Type': 'application/json'
                },
    
    

    and

        const formData = new FormData();
        
        formData.append('author', userID);
        formData.append('text', text);
        formData.append('title', title);
        formData.append('image', image);
        
        const submit = async e => {
                
            e.preventDefault();     
            
            const requestOptions = {
                method: 'POST',
                body: formData
            }
            
            fetch('http://localhost:8000/api/make-post/', requestOptions)
            .then(response => {
                console.log(response)
                if(response.ok){
                    return response.json();
                }
            
            })
            .catch(error => {
                console.log(error)
            })
          
           
        }
        
    

    passed data like that and it works fine


  2. You can do it either using FormData or encode image to base64 and pass in JSON payload.

    1. using FormData
    const formData = new FormData();
    formData.append('image', imageFile);
    let response = await fetch(url, {
            method: 'POST',
            body: formData
        })
            .then(async (resp) => {
                if (!resp.ok) {
                    const body = await tryJson(resp);
                    throw new Error(body ? body.detail : 'Something went wrong');
                }
                return await resp.json();
            })
            .catch((err) => {
                console.log(err);
            });
    
    1. base 64
      Check this.
    Login or Signup to reply.
  3. Convert your fileSelectedHandler function into this

      const fileSelectedHandler = async (event) => {
        let reader = new FileReader();
        reader.readAsDataURL(event.target.files[0]);
        reader.onload = () => {
          setImage(reader.result);
        };
      };
    

    rest keeping other code same, then your backend will be receiving image blob

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