【问题标题】:Django REST Framework image uploadDjango REST Framework 图片上传
【发布时间】:2018-01-15 18:37:51
【问题描述】:

我有模型产品:

def productFile(instance, filename):
    return '/'.join( ['products', str(instance.id), filename] )

class Product(models.Model):
    ...

    image = models.ImageField(
        upload_to=productFile,
        max_length=254, blank=True, null=True
    )
    ...

然后我有序列化器:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = (
            ...
            'image',
            ...
        )

然后我有意见:

class ProductViewSet(BaseViewSet, viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

如何使用 Postman 上传图片?将图像上传到模型的最佳做法是什么?谢谢。

【问题讨论】:

  • 去掉括号,serializer_class = ProductSerializer.. 如果你使用的是ModelViewSet,那么你就不需要再写任何东西了......ViewSet 会为你处理几乎所有的事情。
  • 好的,谢谢,我如何使用邮递员上传图片,或者一些 Ajax 请求?
  • 当我在我的模型中使用它时,我得到一个 ValueError("Cannot serialize function: lambda")
  • @Rony Azrak,我刚刚用有效的解决方案更新了这个问题。使用方法productFile
  • 你能把你的代码发给我,用图像文件在模型中发布数据吗?我想知道它..我的代码向我显示了错误的请求 400 http://....

标签: django image-upload django-rest-framework


【解决方案1】:

您可以创建单独的端点来上传图片,就像这样:

class ProductViewSet(BaseViewSet, viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

    @detail_route(methods=['post'])
    def upload_docs(request):
        try:
            file = request.data['file']
        except KeyError:
            raise ParseError('Request has no resource file attached')
        product = Product.objects.create(image=file, ....)

你可以绕过那个解决方案

——更新: 这是从邮递员上传的方法

【讨论】:

  • 您可以使用邮递员上传,方法是在正文上选择form-data,然后选择文件类型并单击选择文件,在关键字段上写file,请参阅上面的更新。
  • 谢谢!我可以使用像/api/products/33/upload_docs 这样的方法“PUT”的网址吗?
  • 是的,当然可以,但我没有检查您是否可以使用PUT 方法上传
  • 嗯,我刚刚尝试了您的解决方案,但出现错误 {"detail":"Missing filename. Request should include a Content-Disposition header with a filename parameter."} 。你知道我怎样才能“关闭”这个要求吗?再次感谢您! :)
  • 问题出在解析器上,我使用 FileUploadParser 而不是 MultiPartParser :) 谢谢!
【解决方案2】:

我最近开始使用 Django,上传图片时遇到同样的问题。

我完成的所有步骤

  1. 安装 Pillow 以使用 ImageField

    pip install Pillow
    
  2. Settings.py 中添加这些行

    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    MEDIA_URL = '/media/' # 'http://myhost:port/media/'
    
  3. 在model.py中使用ImageField(创建nameFile函数来创建文件夹和文件名)

    def nameFile(instance, filename):
        return '/'.join(['images', str(instance.name), filename])
    
    class UploadImageTest(models.Model):
        name = models.CharField(max_length=100)
        image = models.ImageField(upload_to=nameFile, blank=True, null=True)
    
  4. serializer.py

    class ImageSerializer(serializers.ModelSerializer):
        class Meta:
            model = UploadImageTest
            fields = ('name', 'image')
    
  5. views.py

    class ImageViewSet(ListAPIView):
        queryset = UploadImageTest.objects.all()
        serializer_class = ImageSerializer
    
        def post(self, request, *args, **kwargs):
            file = request.data['file']
            image = UploadImageTest.objects.create(image=file)
            return HttpResponse(json.dumps({'message': "Uploaded"}), status=200)
    
  6. urls.py: 添加这一行

    path('upload/', views.ImageViewSet.as_view(), name='upload'),
    
  7. admin.py:添加这一行(用于签入管理员)

    admin.site.register(UploadImageTest)
    
  8. 在终端中

    python manage.py makemigrations
    python manage.py migrate
    

【讨论】:

  • 您是否尝试在视图中使用MultiPartParser ?另外,我建议您在 ImageViewSet 中为“upload_image”创建新端点
  • 你能告诉如何在请求中更新这个吗?
【解决方案3】:

models.py

from django.db import models

class imageupload(models.Model):
title = models.CharField(max_length=50)
images = models.ImageField('images')

序列化器.py

from rest_framework import serializers
from .models import imageupload

class imageuploadSerializer(serializers.HyperlinkedModelSerializer):

class Meta:
    model = imageupload
    fields= (
        'title',
        'images'
    )

views.py

from rest_framework import viewsets
from .models import imageupload
from .serializers import imageuploadSerializer

class Imageuploadviewset(viewsets.ModelViewSet):
   queryset = imageupload.objects.all()
   serializer_class = imageuploadSerializer

urls.py

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter()
router.register(r'imageupload', views.Imageuploadviewset)

urlpatterns = [
    path('imageupload', include(router.urls)),
]

【讨论】:

    猜你喜欢
    • 2015-08-06
    • 2017-05-13
    • 2016-03-23
    • 2018-01-17
    • 2015-03-18
    • 1970-01-01
    • 2018-10-06
    • 2017-10-23
    • 1970-01-01
    相关资源
    最近更新 更多