【问题标题】:How to upload image by request : Python Django Rest framework如何按请求上传图像:Python Django Rest 框架
【发布时间】:2017-10-30 01:33:34
【问题描述】:

我可以上传现场时间和员工,但我不能上传图片到出席图片

模型

class Attendance(models.Model):
    time = models.DateTimeField(default=datetime.now, blank=True)
    employee = models.ForeignKey(Employee, related_name='employees')
    attendance_pic = models.ImageField(upload_to='attendance_pics',null = True)

序列化器

class AttendanceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Attendance
        fields = '__all__'

观看次数

class AttendanceList(APIView):
    def get(self,request):
        model = models.Attendance
        attendances = model.objects.all()
        serializer = AttendanceSerializer(attendances, many = True)
        return Response(serializer.data)

    def post(self,request):
        now = timezone.now()
        serializer = AttendanceSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        if serializer.is_valid():
            serializer.save(time=now)
            # print (serializer.validated_data)
            # emp = serializer.validated_data.get("employee")
            # obj = models.Attendance.objects.create(time=now, employee=emp)
            return Response("Success", status=status.HTTP_201_CREATED)
            # return Response(AttendanceSerializer(obj).data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

请求

f = open("pic.jpg","rb")
r = requests.post(self.url,data={"employee":ID,"attendace_pic":f})

如果我用 base64.encodebase64 对 f 进行编码,序列化程序将允许 request.data,但它会变为 None,我无法对其进行解码,如果我只是通过它而不编码序列化程序将不允许。

或者我应该使用 FileUploadParser

【问题讨论】:

  • 无法解码是什么意思?您能否向我们展示您的请求处理代码以及发生了什么?
  • @AlVaz 使用 base64.encodebase64 的结果 {'employee': ['25'], 'attendance_pic': ['/9j/4AAQSkZJ...'] } 但是当我使用 decodebase64 时,结果是 None (我认为它没有通过序列化程序)我接下来应该做什么?

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


【解决方案1】:

【讨论】:

  • 根据我的理解,'FileUploadParser' 可以发送唯一的文件,不能发送数据(你可能在我的代码中看到我发送了两个数据,一个是 ID,两个是一个文件)。所以我尝试了“MultiPartParser”,但它似乎不起作用(也许我做错了什么。)
【解决方案2】:

最后,我找到了一些代码来解决这个问题。来自THIS!

请求

f = open("pic.jpg","rb")
data = f.read()
data_url = "data:image/jpg;base64,%s" % base64.b64encode(data)
data_url = data_url[0:22] + data_url[24:]
print(data_url[0:50])
r = requests.post(self.url,data={"employee":ID, "attendance_pic":data_url})
f.close()

Serializers.py

from rest_framework import serializers
from .models import Attendance
from django.core.files.base import ContentFile
import base64
class Base64ImageField(serializers.ImageField):
    def to_internal_value(self, data):
        from django.core.files.base import ContentFile
        import base64
        import six
        import uuid
        print("ininternal")
        # Check if this is a base64 string
        if isinstance(data, six.string_types):
            # Check if the base64 string is in the "data:" format
            print("ininstance")
            if 'data:' in data and ';base64,' in data:
                # Break out the header from the base64 content
                header, data = data.split(';base64,')

            # Try to decode the file. Return validation error if it fails.
            try:
                decoded_file = base64.b64decode(data)
            except TypeError:
                self.fail('invalid_image')

            # Generate file name:
            file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
            # Get the file name extension:
            file_extension = self.get_file_extension(file_name, decoded_file)

            complete_file_name = "%s.%s" % (file_name, file_extension, )

            data = ContentFile(decoded_file, name=complete_file_name)

        return super(Base64ImageField, self).to_internal_value(data)

    def get_file_extension(self, file_name, decoded_file):
        import imghdr

        extension = imghdr.what(file_name, decoded_file)
        extension = "jpg" if extension == "jpeg" else extension

        return extension

class AttendanceSerializer(serializers.ModelSerializer):

    attendance_pic = Base64ImageField(
        max_length=None, use_url=True,
    )

    class Meta:
        model = Attendance
        fields = ('__all__')

【讨论】:

  • 我遇到了类似的问题@Ratchanan。但我不明白你的请求代码。你在哪里写这个请求代码??
猜你喜欢
  • 2018-08-17
  • 1970-01-01
  • 1970-01-01
  • 2021-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多