如何使用带有apollo-upload-client的graphene-file-upload将graphql中的文件上传到Python数据库并进行前端反应?

时间:2019-09-05 20:36:18

标签: python django reactjs graphql apollo

我正在尝试使用graphene-file-upload将文件上传到django后端,该文件具有将后端链接到react前端的突变,在这里我尝试使用apollo-upload客户端将其与graphql链接。 在我的Django模型中,成功上传了一个空文件,但没有上传我选择的真实文件,而是上传了一个空文件。 就像它什么都没有上传{},而是在数据库中创建了实例,并在其中添加了另一个空的故事。

这是我的一些代码。

我的数据库模型。 models.py

class Story(models.Model):
    file = models.FileField(null=True)
    created_at = models.DateTimeField(auto_now_add=True)

MY schema.py

from graphene_file_upload.scalars import Upload

class StoryType(DjangoObjectType):
    class Meta:
        model = Story

class UploadFile(graphene.Mutation):
    story = graphene.Field(StoryType)

    class Arguments:
        file = Upload()

    def mutate(self, info, file):

        for line in file:
            print(line)

        story = Story(file=file)

        story.save()
        return UploadFile(story=story)

我的前端File.js

import React from 'react';
import { Mutation } from 'react-apollo';
import {withStyles} from '@material-ui/core/styles';
import gql from 'graphql-tag';

const styles = theme => ({
    layoutRoot: {}
});


const UploadFile = () => (
  <Mutation
    mutation={gql`
      mutation($file: Upload!) {
        uploadFile(file: $file) {
          story {
            file
          }
        }
      }
    `}
  >
    {mutate => (
      <input
        type="file"
        required
        onChange={({
          target: {
            validity,
            files: [file]
          }
        }) => validity.valid && mutate({ variables: { file } })}
      />
    )}
  </Mutation>
)

export default withStyles(styles, {withTheme: true})(UploadFile);

2 个答案:

答案 0 :(得分:1)

它现在对我有用,我已经在GraphQLView中重写了parse_body,以便它可以正确处理multipart / form-data。

let response = (event, data) => {
    let lambda_response = {     
   "sessionAttributes": {
      "incidentNo":  event.currentIntent.slots.INCIDENT_NO,
    },   
    "dialogAction": {     
        "type": "Close",
        "fulfillmentState": "Fulfilled",
        "message": {       
           "contentType": "PlainText",
           "content": "Hi " + data["User ID"].split('.')[0]+", Your Incident Number " +  "INC"+event.currentIntent.slots.INCIDENT_NO+ " is ," + data["Status"]
        },    
     } 
    };

    return lambda_response;
};

答案 1 :(得分:0)

要求

from python_graphql_client import GraphqlClient
import asyncio
client = GraphqlClient(endpoint="http://localhost:8000/graphql")

客户端 -

def test_archive_upload(client):
    file_header = "data:application/zip;base64,"
    with open("files/Archive.zip", 'rb') as file:
    query = """
            mutation uploadFile($file: Upload) {
                uploadFile(file:$file) {
                    ok
                }
            }
        """
    file = file.read()
    file = file_header + base64.b64encode(file).decode("UTF-8")
    variables = {"file": file}
    data = client.execute(query=query, variables=variables)

运行 -

asyncio.get_event_loop().run_until_complete(test_archive_upload(client))

服务端-

file = file.split(",")
file[0] = file[0]+","
file_type = guess_extension(guess_type(file[0])[0])
file = base64.b64decode(file[1])
with open("files/test"+ file_type, "wb") as w_file:
    w_file.write(file)