2

I can upload the field time and employee but I can't upload an image to the attendance_pic

Model

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)

Serializers

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

Views

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)

Request

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

If I encode f with base64.encodebase64, serializer will allow request.data but it will become None and I can not decode it and if I just pass it without encoding serializer won't allow.

Or I should use FileUploadParser.

  • What does it mean that you cannot decode it? Can you show us your request handling code and what's happening? – AlVaz May 29 '17 at 18:35
  • @AlVaz the result if use **base64.encodebase64** {'employee': ['25'], 'attendance_pic': ['/9j/4AAQSkZJ...']} but when I use **decodebase64**, the result is **None** (I think it not go through serializer) What should I do next? – Ratchanan Prasan May 29 '17 at 19:32

2 Answers2

0

Did you try to use FileUploadParser?

http://www.django-rest-framework.org/api-guide/parsers/#fileuploadparser

pkisztelinski
  • 522
  • 3
  • 14
  • Base on my understanding, 'FileUploadParser' can send the only file, can't send data(you may see in my code I send two data one is ID and two is a file). So I tried 'MultiPartParser' but it seems doesn't work (Maybe I did something wrong.) – Ratchanan Prasan May 29 '17 at 20:56
0

Finally, I found some code for correct this problem. From THIS!

Request

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__')
  • I am having similar issues @Ratchanan . But i dont understand your request code. Where do you write this request code?? – Reactoo Jun 21 '21 at 04:16