使用Tastypie进行React Dropzone多图像上传

时间:2016-01-13 09:43:04

标签: django reactjs tastypie superagent

我尝试使用react-dropzone和tastypie上传多个图像。我无法使用tastypie将图像存储到服务器。文件显示在控制台上,同时在django控制台上显示文件名。< / p>

Models.py

class Rental(models.Model):
    """
    Rents
    """
    ownerName = models.CharField(_("Owner's Name"),max_length=255, blank=True, null = True,
        help_text=_("Owner's Full Name"))
    email = models.CharField(max_length=120,blank=True, null=True)
    phoneNumber = models.PositiveIntegerField(blank=False,null=True,
        help_text=_("Phone number of contact person"))
    listingName =  models.CharField(_("Lisitng Name"), max_length=255, blank=False, null=True,
        help_text=_("Title of the rental space"))
    summary = models.TextField(max_length=500, blank=True, null= True,
        help_text=_("Description of the rental space"))
    property = models.CharField(_("Property type"),max_length=10,null=True)
    room = models.PositiveIntegerField(_("No of Rooms"), blank=False, null=True,
        help_text=_("Number of bedrooms available"))
    price = models.PositiveIntegerField(blank=False,null=True,
        help_text=_("Rental price of the space per month"))
    city =  models.CharField(_("City"), max_length=255, blank=False, null=True,
        help_text=_("City of the rental space"))
    place =  models.CharField(_("Place"), max_length=255, blank=False, null=True,
        help_text=_("Place of the rental space"))
    water = models.CharField(_("water facilities"),max_length=50,null=True,
        help_text=_("Is there water facility?"))
    amenities = models.CharField(_("amenities"),max_length=100,null=True)
    phone_image = models.CharField(max_length=2048,blank=True,null=True,
        help_text=_("image form of the phone number"))
    image = models.FileField(upload_to='/media/')


    def save(self, *args, **kwargs):
        if self.phoneNumber:
            print(self.phoneNumber)
            font = ImageFont.truetype(settings.PHONE_FONT,14)
            phone_image=Image.new("RGBA", (120,16),(255, 255, 255))
            draw = ImageDraw.Draw(phone_image) 
            draw.text((0, 0), self.phoneNumber, (0,0,0), font=font)

            byte_stream = BytesIO()
            phone_image.save(byte_stream, format="png")
            byte_stream.seek(0)

            self.phone_image = base64.b64encode(byte_stream.read()).decode()
        return super(Rental,self).save( *args, **kwargs)

    def __str__(self):
        return self.listingName

    class Meta:
        verbose_name = _("Rent")
        verbose_name_plural = _("Rents")

Api.py

class MultipartResource(object):
    def deserialize(self, request, data, format=None):
        if not format:
            format = request.META.get('CONTENT_TYPE', 'application/json')

        if format == 'application/x-www-form-urlencoded':
            return request.POST

        if format.startswith('multipart'):
            data = request.POST.copy()
            data.update(request.FILES)
            print('data is',data)
            return data

    def put_detail(self, request, **kwargs):
        if request.META.get('CONTENT_TYPE').startswith('multipart') and \
                not hasattr(request, '_body'):
            request._body = ''


        return super(MultipartResource, self).deserialize(request, data, format)



class RentalResource(MultipartResource,ModelResource):
    class Meta:
        queryset = Rental.objects.all()
        resource_name = 'rental'
        allowed_methods = ['get', 'post']
        fields = ['listingName','property','city','place','ownerName','room','water','amenities','price','summary','phoneNumber','email','image']
        filtering = { "property" : ALL , "room":ALL,"price":ALL}
        # authentication = BasicAuthentication()
        authorization = DjangoAuthorization()

Listing.js

var RenderPhotos = React.createClass({
    getInitialState: function () {
        return {
          files:[]
        };
    },

    onDrop(files) {
        console.log('Received files: ', files);
    this.setState({
        files: files
    });
    },

    showFiles() {
        const files = this.state.files || null;
        console.log('files',files);

        if (!files.length) {
            return null;
        }

        return (
            <div>
                <h3>Dropped files: </h3>
                <ul className="gallery">
                    {
                        files.map((file, idx) => {
                            return (
                                <li className="col-md-3" key={idx}>
                                    <img src={file.preview} width={100}/>
                                    <div>{file.name}</div>
                                </li>
                            );
                        })
                    }
                </ul>
            </div>
        );
    },

    render: function () {
      return (
           <div>
                <h3>Photos can bring your space to life</h3>
                <p>Add photos of spaces to give more insight of your space </p>
                <hr/>
                <div className="col-md-12">
                <form method="post" encType="multipart/form-data">
                  <Dropzone onDrop={this.onDrop}
                          style={style}
                          activeStyle={activeStyle}>
                    Try dropping some files here, or click to select files to upload.
                </Dropzone>
                </form>
                {this.showFiles()}
                </div>
                <div className="row continueBtn text-right">
                    <button className="btn how-it-works pull-left" onClick={this.props.previousStep}>Back</button>
                    <button className="btn how-it-works" onClick={this.submitRent}>Next</button>
                </div>
          </div>
      );
    },

        submitRent: function(e) {
          var req = request.post('http://localhost:8000/api/v1/rental/');
          var image = [];
          image = new FormData();
          var that = this;
          var index;
          for (index = 0; index < that.state.files.length; ++index) {
              console.log(that.state.files[index]);
              image.append('files',that.state.files[index]);
          }
          req.send(image);
          console.log('req is',req);
          req.end((err, res) => {
            if (err) {
              console.log('error', err);
            } else {
              console.log('success', res);

            }
          });


    }

});

我做错了什么?为什么图像不存储在服务器上?请在这个问题上赐教。

Django Console where i get the dropped images

1 个答案:

答案 0 :(得分:1)

你的问题在这里:

data.update(request.FILES)
print('data is',data)
return data

这会将'file': <InMemoryUploadedFile>添加到您的捆绑包中。 但是,您的模型并未在任何位置定义“文件”。它定义了'image'(这是你的文件)。 所以你需要做的是:

data['image'] = request.FILES['file]
return data