簡體   English   中英

如何使用 Axios 將文件上傳到 Django REST 框架 API 和反應鈎子形式?

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

我使用 Django Rest Framework 創建了一個 API。 它有一個圖像上傳選項。 但我無法上傳文件。 我使用 Axios 進行 API 調用,並使用鈎子表單進行表單處理。 我發布下面的代碼以便更好地理解。

姜戈:型號:

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)

串行器

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

看法

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)

反應:

表單 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 調用

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);
        })
    }

當我提交表單時,錯誤是, 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. .

安慰有效載荷時,我得到:

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

請幫我...

我找到了解決方案。

原來我必須在 Axios 請求中添加一個標題'Content-Type': 'multipart/form-data'

我在下面發布更新的代碼:

Axios 調用

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);
        })
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM