【问题标题】:Trying to upload image to a FileField model using REST framework or Tastypie尝试使用 REST 框架或 Tastypie 将图像上传到 FileField 模型
【发布时间】:2015-02-06 00:39:45
【问题描述】:

谁能给我一个关于如何使用 REST API 将文件从移动/桌面应用程序上传到基于 Django 的服务器的分步/链接资源?

服务器有一个带有名为“thumbnail”的 FileField 的模型。我可以上传其他数据,但文件似乎是个大问题。

请注意,我不是在谈论使用浏览器/Django 表单上传,而是通过 Http 请求从应用程序上传

api:

from models import Article

class ArticleResource(ModelResource):

    class Meta:
        queryset = Article.objects.all()
        resource_name = 'article'
        filtering = {'title': ALL}
        authorization=Authorization()

我用来制作 Http Requests(模拟移动应用)的独立 python 脚本

url="http://127.0.0.1:8000/articles/api/article/"

data={
    'title':'Tastypie',
    'body':'First Restful client',
    'pub_date':'05/02/2015',
    }
files=  {'thumbnail': open('django.png', 'rb')}
headers =  {'content-type': 'image/png'}
print requests.post(url, files=files)

型号:

class Article(models.Model):
    title = models.CharField(max_length=200)
    body = models.TextField()
    pub_date = models.DateTimeField('date published')
    likes = models.IntegerField(default=0)
    thumbnail = models.FileField(blank=True,null=True,upload_to=get_upload_file_name)
    def __unicode__(self):
        return str(self.title)

编辑:

这行得通:

api:

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()
                photo = Article()
                photo.thumbnail = request.FILES['thumbnail']
                photo.title = request.POST.get('title')
                photo.body=request.POST.get('body')
                photo.pub_date = request.POST.get('pub_date')
                photo.save()
                # ... etc
                return data
            return super(ArticleResource, self).deserialize(request, data, format)

        # overriding the save method to prevent the object getting saved twice 
        def obj_create(self, bundle, request=None, **kwargs):
             pass


class ArticleResource(MultipartResource,ModelResource):

    class Meta:
        queryset = Article.objects.all()
        resource_name = 'article'
        filtering = {'title': ALL}
        authorization=Authorization()

Http 请求 Python 脚本:

url="http://127.0.0.1:8000/articles/api/article/"

data={
    'title':'Tastypie',
    'body':'First Restful client',
    'pub_date':'2015-02-05',
    }
files=  {'thumbnail': open('django.png', 'rb')}

print requests.post(url, data=data, files=files).text

【问题讨论】:

  • 运行脚本时会发生什么?或者更好的是,当您使用curl 时会发生什么,其余数据是否保存而不是文件?还是全都出错了?
  • @LegoStormtroopr 每当我像这样运行脚本时:headers = {'content-type': 'application/json'} print requests.post(url, data=json.dumps(data), headers=headers).text
  • @LegoStormtroopr 每当我像这样运行脚本时:headers = {'content-type': 'application/json'} > print requests.post(url, data=json.dumps(data), headers=headers).text 它运行良好,但是在我编辑它以添加文件的那一刻,它给出了 500 错误:“error_message”:“格式表示'multipart /form-data' 没有可用的反序列化方法。请检查您的序列化器上的 formatscontent_types。"
  • 很高兴它成功了。 +1 发布您的解决方案以帮助他人。

标签: python django rest tastypie


【解决方案1】:

Tastypie 没有任何保存二进制文件的好方法。我会尝试这样的事情:

class ArticleResource(ModelResource):

    class Meta:
        queryset = Article.objects.all()
        resource_name = 'article'
        filtering = {'title': ALL}
        authorization=Authorization()    

    # save the photo
        def deserialize(self, request, data, format=None):
            if not format:
                format = request.META.get('CONTENT_TYPE', 'application/json')

            if format.startswith('multipart'):
                data = request.POST.copy()
                photo = Article()
                photo.thumbnail = request.FILES['thumbnail']
                photo.title = request.POST.get('title')
                # ... etc
                return data
            return super(ArticleResource, self).deserialize(request, data, format)

        # overriding the save method to prevent the object getting saved twice 
        def obj_create(self, bundle, request=None, **kwargs):
            pass

【讨论】:

  • 仍然无法正常工作,每当我使用print requests.post(url, data=data, files=files,headers=headers).text 时,我都会收到一条消息说"error_message": "'utf8' codec can't decode byte 0x89 in position 409: invalid start byte. You passed in '--da8f68c94da44747ae6980923316c7ec\\r\\nContent-Disposition: form-data,但是当我使用requests.post(url, data=data, files=files).text 时,我会收到{"error_message": "The format indicated 'multipart/form-data' had no available deserialization method. Please check your ``formats`` and ``content_types
  • 你为什么要这样做?我不明白。
  • 经过一些小的编辑(例如将反序列化函数放在自己的类中)后,它实际上工作了。谢谢!
猜你喜欢
  • 1970-01-01
  • 2022-11-26
  • 1970-01-01
  • 2018-10-31
  • 2018-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多