Home > Back-end >  The code is forcing the user to change the image also when he want to change only other properties o
The code is forcing the user to change the image also when he want to change only other properties o

Time:04-11

Hello everyone I have a blog platform, the user can add and edit blog. I used Django and Django Rest Framework to build the website, and for the frontend ReactJS. My problem is when I edit blog I couldn't save the changes until I change the image. This is the error when I just update title without change image.

models.py

def upload_path(instance, filename):
   return 'img/{filename}'.format(filename=filename)

class Blog(models.Model):
   title = models.CharField(max_length=250)
   slug = models.SlugField(max_length=250, unique=True, null=True)
   content = models.TextField()
   published = models.DateTimeField(default=timezone.now)
   author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='blog_blog')

   objects = models.Manager()  # default manager
   image = models.ImageField(_("Image"), upload_to=upload_path, null=True)

   class Meta:
      def __str__(self):
         return self.title

views.py

class EditBlog(generics.UpdateAPIView):
   permission_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
   serializer_class = BlogSerializer
   queryset = Blog.objects.all()

in React edit.js

import React, { useState, useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import axiosInstance from '../../../axios';
import WriteCss from '../../../assets/CSSStyle/WriteBlog.module.css';
import { Image } from 'antd';



export function Edit() {

const navigate = useNavigate();
const { id } = useParams();
const initialFormData = Object.freeze({
    title: '',
    slug: '',
    content: '',
});

const [formData, updateFormData] = useState(initialFormData);

const [postimage, setPostImage] = useState(null);


useEffect(() => {
    axiosInstance.get('admin/edit/postdetail/'   id).then((res) => {
        updateFormData({
            ...formData,
            ['title']: res.data.title,
            ['slug']: res.data.slug,
            ['content']: res.data.content,
            ['image']: res.data.image,

        });
    });
}, [updateFormData]);

const handleChange = (e) => {
    if ([e.target.name] == 'image') {
        setPostImage({
            image: e.target.files,
        });
        console.log("d",e.target.files);
    } 
    else {
        updateFormData({
            ...formData,
            [e.target.name]: e.target.value,
        });
    }
}

const handleSubmit = (e) => {
    e.preventDefault();
    console.log(formData);

    let ss = new FormData();
    ss.append('title', formData.title);
    ss.append('slug', formData.slug);
    ss.append('content', formData.content);
    ss.append('image', postimage.image[0]);

    axiosInstance.patch(`admin/edit/`  id   '/', ss,  {
        headers:{
            Authorization: `JWT ${localStorage.getItem('refresh_token')}`
    },
    },)
    .then((res) => {
        // navigate('/admin/');
    });
    
};

return (
<>
<div className='container' style={{marginTop:"7.5rem"}}>
<h1 className={WriteCss.h}>Update Your Article</h1>
    <form>
        <div className='row'>
            <div className='col-12 col-md-12 col-lg-12'>
                <input
                    className={WriteCss.writeInput}
                    placeholder="Type your title ..."
                    type="text"
                    autoFocus={true}
                    id="title"
                    label="Post Title"
                    name="title"
                    autoComplete="title"
                    value={formData.title}
                    onChange={handleChange}
                />
                <input
                    className={WriteCss.writeInput}
                    placeholder="slug will be generated based on title"
                    id="slug"
                    label="Post slug"
                    name="slug"
                    autoComplete="slug"
                    value={formData.slug}
                    onChange={handleChange}
                />
            </div>
            <div className='row'>
                <div className='col-12 col-md-12 col-lg-12'>
                    <textarea
                        className={WriteCss.writeText}
                        placeholder="Type your blog..."
                        type="text"
                        id="content"
                        label="content"
                        name="content"
                        autoComplete="content"
                        value={formData.content}
                        onChange={handleChange}
                        />
                </div>
            </div>
            <Image
                src={formData.image}
                style={{ width: '200px', height: '200px' }}/>
            <input
                accept="image/*"
                id="post-image"
                onChange={handleChange}
                name="image"
                type="file"/>
            <div className='row'>
                <div className={`col-12 col-md-12 col-lg-12 ${WriteCss.col}`}>
                <button className={WriteCss.writeSubmit} type="submit" onClick={handleSubmit}>
                    Update
                </button>
                </div>
             </div>
          </div>
        </form>
      </div>
    </>
   )}

 export default Edit

Any hint or guidance will be really helpful for me to complete the project because I have been stuck in it for more than two weeks.

Thanks

CodePudding user response:

The problem is with handleSubmit, you cannot read the value of postimage if it is null:

const handleSubmit = (e) => {
    e.preventDefault();
    console.log(formData);

    let ss = new FormData();
    ss.append('title', formData.title);
    ss.append('slug', formData.slug);
    ss.append('content', formData.content);

    if (postimage != null) {
       ss.append('image', postimage.image[0]);
    }

    axiosInstance.patch(`admin/edit/`  id   '/', ss,  {
        headers:{
            Authorization: `JWT ${localStorage.getItem('refresh_token')}`
    },
    },)
    .then((res) => {
        // navigate('/admin/');
    });
    
};

Remember to set required=False for the image field of BlogSerializer.

  • Related