title: PyQt5 and Django : How to Upload Image using HTTP Request ( Multipart-form )?
body: <p>currently I am working in a project to create a seller application where the seller can upload the menu picture and some additional information such as the price and the name of the menu. but I stuck at the POST request method because in this time I have to upload an image with some text data instead of only text data. </p>
  
  <p>I am using PyQt5.  </p>
  
  <p>This is my API web server. I am using Django Rest Framework to build that.</p>
  
  <p>[<img src="https://i.stack.imgur.com/m7ZHL.png" alt="API Structure"></p>
  
  <p>This is the menu model:</p>
  
  <pre><code>class Menu(models.Model):
      image = models.ImageField(upload_to=path_and_rename)
      name = models.CharField(max_length=100)
      price = models.IntegerField()
      category = models.IntegerField()
      availability = models.BooleanField(default=False)
      # booked = models.IntegerField()
      sellerID = models.ForeignKey(Seller, on_delete=models.PROTECT)
  </code></pre>
  
  <p>This the Menu Serializers:</p>
  
  <pre><code>class MenuSerializer(serializers.ModelSerializer):
      class Meta:
          model = models.Menu
          fields = ('id', 'image', 'name', 'price', 
                    'category','availability', 'sellerID')
  </code></pre>
  
  <p>This is the menu viewset:</p>
  
  <pre><code>class MenuViewset(viewsets.ModelViewSet):
      queryset = models.Menu.objects.all()
      serializer_class = serializers.MenuSerializer
  </code></pre>
  
  <p>I have tried to the method in this answer: <a href="https://stackoverflow.com/questions/21158102/upload-files-through-http-post-in-pyside-pyqt">here</a></p>
  
  <p>This is my implementation to that method:</p>
  
  <pre><code>def upload(self):
      file1 = QFile("/home/shalahuddin/Desktop/jamu.jpg")
      file1.open(QFile.ReadOnly)
      url = "http://127.0.0.1:8000/api/menu/"
  
      nama = QByteArray()
      nama.append("ABCD")
  
      harga = QByteArray()
      harga.append(str(999))
  
      kategori = QByteArray()
      kategori.append(str(0))
  
      ada = QByteArray()
      ada.append(str(True))
  
      idseller = QByteArray()
      idseller.append(str(2))
  
  
      data = {"name": nama, "price": harga, "category": kategori, "availability": ada, "sellerID": idseller}
      files = {"image": file1}
      multipart = self.construct_multipart(data, files)
      request_qt = QNetworkRequest(QUrl(url))
      request_qt.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader,
                           'multipart/form-data; boundary=%s' % multipart.boundary())
      self.manager = QtNetwork.QNetworkAccessManager()
      self.manager.finished.connect(self.handleResponseMenu)
      self.manager.post(request_qt, multipart)
  
  def handleResponseMenu(self, reply):
      er = reply.error()
      data = json.loads(str(reply.readAll(), 'utf-8'))
      file = open("/home/shalahuddin/Desktop/testfile.txt", "w")
  
      file.write(str(reply))
      if er == QtNetwork.QNetworkReply.NoError:
          bytes_string = reply.readAll()
          data = json.loads(str(bytes_string, 'utf-8'))
          # print(data)
          QMessageBox.information(self, "Menu", "Upload Success!")
  
      else:
          errorMessage = "Error occured: " + str(er) + "\n" + str(reply.errorString())
          QMessageBox.critical(self, "Error Done", errorMessage)
  
  def construct_multipart(self, data, files):
      multiPart = QHttpMultiPart(QHttpMultiPart.FormDataType)
      for key, value in data.items():
          textPart = QtNetwork.QHttpPart()
          textPart.setHeader(QNetworkRequest.ContentDispositionHeader,
                             "form-data; name=\"%s\"" % key)
          textPart.setBody(value)
          multiPart.append(textPart)
  
      for key, file in files.items():
          imagePart = QtNetwork.QHttpPart()
          # imagePart.setHeader(QNetworkRequest::ContentTypeHeader, ...);
          fileName = QFileInfo(file.fileName()).fileName()
          imagePart.setHeader(QtNetwork.QNetworkRequest.ContentDispositionHeader,
                              "form-data; name=\"%s\"; filename=\"%s\"" % (key, fileName))
          imagePart.setBodyDevice(file)
          multiPart.append(imagePart)
      return multiPart
  </code></pre>
  
  <p>But I got error 302 Bad Request as the result. The JSON data that I get is:</p>
  
  <pre><code>{
    'image': ['No file was submitted.'], 
    'name': ['Ensure this field has no more than 100 characters.', 
             'Null characters are not allowed.'], 
    'price': ['This field is required.'], 
    'category': ['This field is required.'], 
    'sellerID': ['This field is required.']
  }
  </code></pre>
  
  <p>Therefore, I would like to know where is the problem? I have tried to trace it repeatedly but still, give no answer. This is my first time to using multipart request. </p>