简体   繁体   中英

How to upload file to Django rest framework API using Axios and react hook form?

I have created an API using Django Rest Framework. It has an image uploading option. But I can not upload the file. I am using Axios for API calls and react hook form for form handling. I am posting the code below for better understanding.

Django: Model:

class BlogModel(models.Model):
    user = models.ForeignKey(user_model.User, on_delete=models.CASCADE, related_name="user_blog")
    blogtitle = models.CharField(max_length=250)
    blogcontent = models.TextField()
    blogimg = models.ImageField(upload_to="blog_image", blank=True)
    slug = models.SlugField(max_length=250, unique=True)
    tags = models.ManyToManyField(BlogTagsModel, related_name='blog_tags', blank=True, null=True)
    published_date = models.DateTimeField(auto_now_add=True)
    edit_date = models.DateTimeField(auto_now=True)

Serializer

class BlogSerializer(serializers.ModelSerializer):
    class Meta:
        model = blog_model.BlogModel
        fields = '__all__'
        extra_kwargs = {
            'user': {'read_only': True},
            'slug': {'read_only': True},
        }

View

class BlogPostView(generics.ListCreateAPIView):
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    serializer_class = blog_ser.BlogSerializer
    queryset = blog_model.BlogModel.objects.all()

    def perform_create(self, serializer):
        rand_num = random.randint(99, 222)
        blog_slug_str = f"{serializer.validated_data.get('blogtitle')}{rand_num}"
        sample_string_bytes = blog_slug_str.encode("ascii")
        base64_bytes = base64.b64encode(sample_string_bytes)
        slug = base64_bytes.decode("ascii")
        serializer.save(user=self.request.user, slug=slug)

React:

Form JSX

                <form className="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4" onSubmit={handleSubmit(onSubmit)}>
                    <div className="mb-4">
                        <label
                            className="block text-gray-700 text-sm font-bold mb-2"
                            htmlFor="title"
                        >
                            Title
                        </label>
                        <input
                            className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                            id="title"
                            type="text"
                            {...register('title', { required: true })}
                        />
                        {errors.title && <p className="text-red-500 text-xs italic">Title is required</p>}
                    </div>
                    <div className="mb-4">
                        <label
                            className="block text-gray-700 text-sm font-bold mb-2"
                            htmlFor="image"
                        >
                            Image
                        </label>
                        <input
                            className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                            id="image"
                            type="file"
                            {...register('image', { required: true })}
                        />
                        {errors.image && <p className="text-red-500 text-xs italic">Image is required</p>}
                    </div>
                    <div className="mb-4">
                        <label
                            className="block text-gray-700 text-sm font-bold mb-2"
                            htmlFor="details"
                        >
                            Details
                        </label>
                        <textarea
                            className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                            id="details"
                            {...register('details', { required: true })}
                        />
                        {errors.details && <p className="text-red-500 text-xs italic">Details is required</p>}

                    </div>
                    <button
                        className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
                        type="submit"
                    >
                        Submit
                    </button>
                </form>

Axios Call

const onSubmit = data => {
        console.log(data.image['0']);
        const payload = {
            blogtitle: data.title,
            blogcontent: data.details,
            blogimg: data.image,
        }
        console.log(payload);
        myAxios.post('/api/post/', payload).then(res => {
            console.log(res);
        }).catch(err => {
            console.log(err.response.data);
        })
    }

When I am submitting the form the error is saying, The submitted data was not a file. Check the encoding type on the form. The submitted data was not a file. Check the encoding type on the form. .

When consoling the payload, I am getting:

{
    "blogtitle": "nok",
    "blogcontent": "asasa",
    "blogimg": {
        "0": {}
    }
}

Please Help Me...

I have found the solution.

Turns out I have to add a header 'Content-Type': 'multipart/form-data' to the Axios Request.

I am posting the updated code below:

Axios Call

const onSubmit = data => {
        const payload = {
            blogtitle: data.title,
            blogcontent: data.details,
            blogimg: data.image['0'],
        }
        console.log(payload);
        myAxios.post('/api/post/', payload, {
            headers: {
                'Content-Type': 'multipart/form-data'
            }
        }).then(res => {
            console.log(res);
        }).catch(err => {
            console.log(err.response.data);
        })
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM