【问题标题】:React Dropzone Multiple Image at once in Tastypie在 Tastypie 中一次反应 Dropzone 多个图像
【发布时间】:2016-01-18 19:30:57
【问题描述】:

我尝试使用 react-dropzone 和tastepie上传多个图像。我只能使用tastepie 而不是多个将一个图像存储到服务器。控制台和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);

            }
          });


    }

});

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

【问题讨论】:

  • 你检查 submitRent 有没有抛出任何错误?
  • 不。它不会抛出任何错误。
  • 我在控制台上检查过,它显示了所有文件。
  • 你可以在控制台imgur.com/1UHYZAe看到输出
  • hmmm.. 那么您必须检查您的服务逻辑是否存储了从客户端传递的所有图像?

标签: python django reactjs tastypie superagent


【解决方案1】:

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

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

【讨论】:

  • 你的意思是说我必须为图像创建一个单独的表?
  • 是的,您需要一个单独的表格。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-19
  • 2021-05-05
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
  • 2015-04-21
相关资源
最近更新 更多