使用Django和React上传图片

amrnrhlw  于 2023-08-08  发布在  Go
关注(0)|答案(1)|浏览(131)

我正在尝试使用Django和React上传包含其他表单数据的图像。
400个错误请求
第一个API应该创建一个没有图像的新产品,然后第二个API将编辑产品并添加图像。
当我在客户端创建一个产品时,第一个API的状态为200,第二个API的状态为400。
使用FileReader允许浏览器读取图像的URL。
下面是我的代码:

React

export default function Add(){

    let [formData , setFormData] = useState({namee: '',price: ''})
    let [files , setFiles] = useState(null)
   
  

    const handleInputChange = (event) => {
        const { name , value } = event.target
        setFormData({...formData, [name] : value})
    }

    const handleImageChange = (event) => {

      const file = event.target.files[0]
      const reader = new FileReader()
      reader.addEventListener("load", function() {
        console.log(reader.result)
        setFiles(reader.result)
      })
      reader.readAsDataURL(file)
      
    }

    const handleSubmit = (event) => {
      
      event.preventDefault()
      const { namee, price } = formData
      const formDataObj1 = new FormData()
      const formDataObj2 = new FormData()
      formDataObj1.append('namee', namee)
      formDataObj1.append('price', price)
      formDataObj2.append('image', files)
      
      if(files){
        fetch('http://127.0.0.1:8000/add' , 
            {
                method: "POST",
                body: formDataObj1,
            }
        )
            .then(response => {
                if(response.ok){
                  
                   fetch('http://127.0.0.1:8000/addimage', 
                   {
                    method: "PUT",
                    body: formDataObj2,
                   })
                   .then(response => {
                    console.log(response)
                    if(response.ok){
                      alert('Your Product has been added :)')
                    }
                    else{
                      console.error('Form submission failed.')
                  }
                   })
                   .catch(error => {
                      console.log(error)
                   })
                }
                else{
                    console.error('Form submission failed.')
                }
            })
                .catch(error => {
                    console.log('Form submission failed.' , error)
                })
    }
    else{
      console.log('files is empty')
    }
  }

    const imgStyle = {
        marginBottom: '10px'
    }

    return (
        <div className="c3">
        <div id="info" className="center">
          <h1>Product</h1>
          <form onSubmit={handleSubmit} >
            <div className="txt_field">
              <input type="text" name="namee" value={formData.namee} onChange={handleInputChange} required/>
              <span></span>
              <label>Name</label>
            </div>
            <div className="txt_field">
              <input type="number" name="price" value={formData.price} onChange={handleInputChange} required/>
              <span></span>
              <label>Price</label> 
            </div>
            <div style={imgStyle}>
              <input type="file" name="image" onChange={handleImageChange}  required/>
              <span></span>
            </div>
            <input  type="submit" value="Confirm" className="ss"/>
          </form>
        </div>
      </div>
    )

}

字符串

Django

# views

class AddProduct(generics.CreateAPIView):

    serializer_class = ProductSerializer

    def post(self , request , format=None):
        name = request.data['namee']
        price = request.data['price']
        Product.objects.create(name=name, price=price)
        return Response('product successfuly added', status=status.HTTP_200_OK)

class AddProductImage(APIView):

    serializer_class = AddImageProSerializer
    parser_classes = ( MultiPartParser, parsers.JSONParser)   

    def put(self , request ):
        product = Product.objects.last()
        serializer = AddImageProSerializer(data=request.data , instance = product)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_200_OK)

# model

class Product(models.Model):
    name = models.CharField(max_length=200,null=True)
    price = models.FloatField(null=True)
    digital = models.BooleanField(default=False,null=True,blank=False)
    image = models.ImageField(upload_to='images/',null=True,blank=True)

    def __str__(self):
        return self.name


# serializers

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ['id' , 'name', 'price']

class AddImageProSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ['image']

# urls

urlpatterns = [
    path('', views.ProductView.as_view(), name='ProductView'),
    path('cart', views.OrderItemView.as_view(), name='OrderItemView'),
    path('orders', views.OrderView.as_view(), name='OrderView'),
    path('add', views.AddProduct.as_view(), name='Add'),
    path('addimage', views.AddProductImage.as_view(), name='Addimage'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

brjng4g3

brjng4g31#

我发现使用httpie之类的东西来测试Django API很有帮助,而不是同时开发和调试两端。这使您可以确认它是否按预期响应。一旦开始工作,你就可以在你的react应用程序中使用httpie的设置了。
我主要使用axios(而不是fetch)与Django模型视图集(而不是API视图)。在这种情况下,如果你的模型有一个FileField或ImageField,Django默认会简单地“处理”上传。
Django期望的是一个多部分的上传,因为你发送的是表单数据和一个文件。**这需要在客户端(fetch或axios)的头中设置,我注意到你没有这样做。如果这不起作用,而您需要更多帮助,请考虑在您已经发布的urls.py、models.py和serializers.pyviews.py。

相关问题