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.

2
  • What does it mean that you cannot decode it? Can you show us your request handling code and what's happening? Commented May 29, 2017 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? Commented May 29, 2017 at 19:32

2 Answers 2

0

Did you try to use FileUploadParser?

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

Sign up to request clarification or add additional context in comments.

1 Comment

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.)
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__')

1 Comment

I am having similar issues @Ratchanan . But i dont understand your request code. Where do you write this request code??

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.