在Tastypie中同时反射Dropzone多个图像

时间:2016-01-18 08:28:03

标签: python django reactjs tastypie superagent

我尝试使用react-dropzone和tastypie 上传多个图片。我只能使用tastypie而不是多个将一个图像存储到服务器。多个图像文件显示在控制台和django上控制台,但只有多个图像中的最后一个图像才会发送到服务器。

这是我的代码

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
        return super(MultipartResource, self).deserialize(request, data, format)


    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).put_detail(request,**kwargs)

    def patch_detail(self, request, **kwargs):
        if request.META.get('CONTENT_TYPE', '').startswith('multipart/form-data') and not hasattr(request, '_body'):
             request._body = ''
        return super(MultipartResource, self).patch_detail(request, **kwargs)



class RentalResource(MultipartResource,ModelResource):
    class Meta:
        queryset = Rental.objects.all()
        resource_name = 'rental'
        allowed_methods = ['get', 'post','put']
        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()

Models.py

class Rental(models.Model):
    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='uploads')
    is_published = models.BooleanField(default=True)
    created_on = models.DateTimeField(auto_now_add=True)
    modified_on = models.DateTimeField(auto_now_add=True)

    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")

Listing.jsx

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) {
         // want to store the data so that when user reverts back to this form the data should be in same previous state 
          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('image',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);

            }
          });


    }

});

我做错了什么?为什么只发送一张图片而不是多张图片?

1 个答案:

答案 0 :(得分:0)

如果Django中出现多个图像,则会向服务器发送多个图像。只保存一个图像的原因是:

  1. 对反序列化数据进行的密钥查找tastypie只会返回单个项目。您可能必须覆盖资源上的dehydrate_image,如果您想要一个文件列表,如果bundle.data是QueryDict,则调用getlist
  2. Rental.image是一个ImageField,只能存储一个文件。要存储多个文件,您需要更改架构。