【问题标题】:Upload an Image to Django Rest Framework using Requests Library使用请求库将图像上传到 Django Rest Framework
【发布时间】:2020-09-23 03:40:54
【问题描述】:

我正在尝试创建一个用于创建帖子的 api 端点,用户可以选择是否要单独上传文本(推文)或图像或两者,我的序列化程序中有一个验证方法,如果没有图像也文本已发送,但无论我发送的是什么,它都会在每次尝试时引发错误。 我不完全确定这是序列化程序类错误还是我为发送 POST 请求而编写的脚本

  • 这是脚本:
import os
import requests
from PIL import Image

ENDPOINT = "http://0.0.0.0:8000/"

IMG = os.path.join(os.getcwd(), "img/img.jpg")


def send_request(method="GET", path="/", data=None, img_path=None):
    if data is None:
        data = {}
    if img_path is not None:
        with open(img_path, 'rb') as image:
            img_file = {"image": image}
            req = requests.request(method, ENDPOINT + path, data=data, files=img_file)
    else:
        req = requests.request(method, ENDPOINT + path, data=data)
    return req.text


res = send_request(method="POST", path="api/posts/create/", data={"user": 1, "content": ""}, img_path=IMG)

print(res)
  • 这是模型类:
from django.db import models
from django.conf import settings
import uuid
import os


class PostQuerySet(models.QuerySet):
    pass



class PostManager(models.Manager):
    def get_queryset(self):
        return PostQuerySet(self.model, using=self._db)


def upload_post_image(instance, filename):
    file_extension = filename.split('.')[-1]
    filename = f"{uuid.uuid4()}.{file_extension}"

    print(os.path.join())
    return os.path.join('post_image/', filename)



class Post(models.Model):
    user        = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    content     = models.TextField(null=True, blank=True, max_length=255)
    image       = models.ImageField(null=True, upload_to=upload_post_image)

    def __str__(self):
        return str(self.content)[:50]

  • 这是序列化程序类:
from rest_framework import serializers

from .models import Post


class PostSerializer(serializers.Serializer):

    class Meta:
        model = Post
        fields = ('user', 'content', 'image')

    def validate(self, data):
        content = data.get("content", None)
        image = data.get("image", None)
        if content == '':
            content = None

        if image is None and content is None:
            raise serializers.ValidationError("Content or an Image must be provided")
        return data
  • 以下是我的看法:
from django.core.exceptions import ObjectDoesNotExist
from rest_framework import generics, mixins, permissions, authentication
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.views import APIView

from .serializers import PostSerializer
from .models import Post


class PostManageAPIView(
    APIView,
    mixins.UpdateModelMixin,
    mixins.DestroyModelMixin,
    mixins.CreateModelMixin,
    mixins.ListModelMixin):

    def get(self, request, *args, **kwargs):
        print(self.request.GET)
        return Response({"message": "This is just a test"})


class PostDetailAPIView(generics.RetrieveAPIView):
    serializer_class = PostSerializer
    permission_classes = ()
    authentication_classes = ()
    queryset = Post.objects.all()

    def get_object(self, *args, **kwargs):
        kwargs = self.kwargs
        kw_id = kwargs.get('id')
        try:
            return Post.objects.get(id=kw_id)
        except ObjectDoesNotExist:
            return Response({})


class CreatePost(generics.CreateAPIView):
    serializer_class        = PostSerializer
    permission_classes      = ()
    authentication_classes  = ()

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

当我运行 python 脚本发送请求时,我总是收到验证错误,提示必须提供内容或图像

【问题讨论】:

    标签: python django django-rest-framework python-requests django-serializer


    【解决方案1】:

    您必须通过视图的 request.FILES 属性检查是否有文件。您发布的文件不会在 POST 正文中。

    如果没有发布文件,request.FILES 属性将为空列表。

    您可以这样做:(请注意,在 CreateAPIView 的 create 方法中,序列化程序已经在其上下文中拥有请求对象)

    class PostSerializer(serializers.Serializer):
    
    class Meta:
        model = Post
        fields = ('user', 'content', 'image')
    
    def validate(self, data):
        content = data.get("content", None)
        request = self.context['request']
        # you dont need to set content explicitly to None
    
        if not request.FILES and not content:
            raise serializers.ValidationError("Content or an Image must be provided")
        return data
    

    【讨论】:

    • 现在 Django 在“/venv/lib/python3.8/site-packages/rest_framework/serializers.py”中引发了一个“NotImplementedError”,说:必须实现NotImplementedError: create()`。 `
    • 而不是类serializers.Serializer,继承自serializers.ModelSerializer,我想它会自动为你实现create方法
    • 成功了!非常感谢您能否简单地告诉我序列化程序和模型序列化程序之间的真正区别是什么?我是 Django 新手,所以我仍然不知道什么时候该使用什么
    • 当然。在 ModelSerializer 中,您可以选择要序列化的模型字段。序列化程序已经知道您的模型及其字段,以及序列化它们的方式。您不必为每个模型字段显式定义序列化器字段。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-23
    • 2019-03-24
    • 2022-06-14
    • 2018-01-17
    • 1970-01-01
    • 2019-12-02
    相关资源
    最近更新 更多