Реагируйте: Как отправить multipart / form-data в базу данных - PullRequest
0 голосов
/ 31 марта 2020

В настоящее время я настраиваю загрузку файлов с помощью React для внешнего интерфейса и Django для внутреннего интерфейса. Более конкретно, я хочу передать файл + некоторые данные в мою базу данных через API.

Но при загрузке файла я получаю сообщение об ошибке: "Представленные данные не были файлом. Проверьте тип кодировки в форме."

модели .py (Django)

class Story (models.Model):
    title = models.CharField(max_length=100,blank=False)
    content = models.TextField(blank=False)
    author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    audio = models.FileField(default='SOME STRING', upload_to='audio_stories/',null=True, validators=[validate_file_extension_audio])


    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('story-detail', kwargs={'pk': self.pk})

serializers.py (Django)

class StorySerializer(serializers.ModelSerializer):
  class Meta:
    model = Story 
    fields = '__all__'

MultiPartParser используется для передачи файла + данные.

api.py (Django)

class StoryViewSet(viewsets.ModelViewSet) (Django):
    serializer_class = StorySerializer
    parser_classes = (MultipartJsonParser, parsers.JSONParser) 

    queryset = Story.objects.all()


    permission_classes = [
        permissions.IsAuthenticated
    ]

    def perform_create(self, serializer):
        serializer.save(author=self.request.user) 

utils.py (Django)

class MultipartJsonParser(parsers.MultiPartParser):

    def parse(self, stream, media_type=None, parser_context=None):
        result = super().parse(
            stream,
            media_type=media_type,
            parser_context=parser_context
        )
        data = {}
        # find the data field and parse it
        data = json.loads(result.data["data"])
        qdict = QueryDict('', mutable=True)
        qdict.update(data)
        return parsers.DataAndFiles(qdict, result.files)

В истории действий. js (React)

import axios from "axios";
import { tokenConfig } from './auth';
import { createMessage, returnErrors } from "./messages";



import {ADD_STORY} from "./types";

const apiBase = "http://localhost:8000/api";



export const addStory = story => (dispatch, getState) => {
  axios
    .post(apiBase +"/story/", story, tokenConfig(getState))
    .then(res => {
      dispatch(createMessage({ addStory: "Story Added" }));
      dispatch({
        type: ADD_STORY,
        payload: res.data
      });
    })
    .catch(err =>
      dispatch(returnErrors(err.response.data, err.response.status))
    );
};

В компонентах create_story. js (React)

import React, { Component } from "react";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { addStory } from "../../actions/story";


export class CreateStory extends Component {
  state = {
    title: "",
    content:""
  };

  static propTypes = {
    addStory: PropTypes.func.isRequired
  };

  onChange = e => this.setState({ [e.target.name]: e.target.value });

  onSubmit = e => {
    e.preventDefault();
    const { title,content, audio} = this.state;
    const story = { title, content, audio};
    this.props.addStory(story);
    this.setState({
      title: "",
      content:"",
      audio:""
    });
  };

  render() {
    const {title, content, audio} = this.state;
    return (
      <div className="card card-body mt-4 mb-4">
        <h2>Add Story</h2>
        <form onSubmit={this.onSubmit}>

          <div className="form-group">
            <label>Title</label>
            <input
              className="form-control"
              type="text"
              name="title"
              onChange={this.onChange}
              value={title}
            />
             </div>
           <div className="form-group">
            <label>Content</label>
            <input
              className="form-control"
              type="text"
              name="content"
              onChange={this.onChange}
              value={content}
            />
          </div>

           <div className="form-group">
            <label>Audio</label>
            <input
              className="form-control"
              type="file"
              name="audio"
              onChange={this.onChange}
              value={audio}
            />
          </div>

         <div className="form-group">
            <button type="submit" className="btn btn-primary">
              Submit
            </button>
          </div>
        </form>
      </div>
    );
  }
}
export default connect(
  null,
  { addStory }
)(CreateStory);

У меня проблемы с отслеживанием ошибки в моем коде. Я предполагаю, что форма реагирования не обеспечивает правильный формат данных, то есть данные формы. Но я не знаю, как и как это изменить. Без загрузки файла я смог успешно передать данные в свою базу данных.

Большое спасибо.

1 Ответ

0 голосов
/ 31 марта 2020

Ваша функция onChange в create_story.js не собирает файл. Возможно, вам придется переформатировать эту функцию, например:

onChange = (e) => {
        if(e.target.name === 'audio') {
            this.setState({
                [e.target.name]: e.target.files[0]
            }, () => console.log(this.state.audio))

        } else {

            this.setState({
                [e.target.name]: e.target.value
            }, () => console.log(this.state))
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...