#Files aren't being uploaded

16 messages · Page 1 of 1 (latest)

winter galleon
#

Received data:

'evidence_set': [<InMemoryUploadedFile: DSC_6306_11zon (1).jpg (application/octet-stream)>, <InMemoryUploadedFile: DSC_6306_11zon.jpg (application/octet-stream)>]}>```

Received files: 
`<MultiValueDict: {'evidence_set': [<InMemoryUploadedFile: DSC_6306_11zon (1).jpg (application/octet-stream)>, <InMemoryUploadedFile: DSC_6306_11zon.jpg (application/octet-stream)>]}>`
#

Serializers:-

class EvidenceSerializer(serializers.ModelSerializer):
    evidence = serializers.FileField()

    class Meta:
        model = Evidence
        fields = ['evidence']

class ViolationSerializer(serializers.ModelSerializer):
    evidence_set = EvidenceSerializer(many=True, write_only=True)
    violation_type = serializers.SlugRelatedField(
        queryset=ViolationType.objects.all(), slug_field="name"
    )
    subject = serializers.SlugRelatedField(
        queryset=Subject.objects.all(), slug_field="subject_name"
    )
    teacher = serializers.SlugRelatedField(
        queryset=Teacher.objects.all(),
        slug_field="name",
        required=False,
        allow_null=True,
    )

    class Meta:
        model = Violation
        fields = [
            "student_name",
            "parent_id",
            "subject",
            "department",
            "grade",
            "teacher",
            "compliance_analyst_id",
            "deputy_hod",
            "hod",
            "description",
            "violation_type",
            "title",
            "evidence_set",
        ]

    def create(self, validated_data):
        evidence_data = validated_data.pop("evidence_set")
        violation = Violation.objects.create(**validated_data)
        for evidence in evidence_data:
            Evidence.objects.create(violation=violation, **evidence)
        return violation
#

Models:-

class Violation(models.Model):
    student_name = models.CharField(max_length=300)
    parent_id = models.CharField(max_length=300)
    subject = models.ForeignKey(
        to=Subject, on_delete=models.CASCADE, null=True, blank=True
    )
    department = models.CharField(max_length=300)
    grade = models.CharField(
        max_length=300,
        choices=[
            ("1", "1"),
            ("2", "2"),
            ("3", "3"),
            ("4", "4"),
            ("5", "5"),
            ("6", "6"),
            ("7", "7"),
            ("8", "8"),
            ("9", "9"),
            ("10", "10"),
            ("11", "11"),
            ("12", "12"),
        ],
    )
    teacher = models.ForeignKey(
        to=Teacher, on_delete=models.CASCADE, null=True, blank=True
    )
    compliance_analyst_id = models.CharField(max_length=300)
    deputy_hod = models.CharField(max_length=300)
    hod = models.CharField(max_length=300)
    description = models.CharField(max_length=500)
    violation_type = models.ForeignKey(
        to=ViolationType, on_delete=models.CASCADE, null=True, blank=True
    )
    title = models.CharField(max_length=300)
    created_time = models.DateTimeField(auto_now_add=True)
    updated_time = models.DateTimeField(auto_now=True)


class Evidence(models.Model):
    violation = models.ForeignKey(
        to=Violation, on_delete=models.CASCADE, null=True, blank=True
    )
    evidence = models.FileField(upload_to="evidence", max_length=100)
    created_time = models.DateTimeField(auto_now_add=True)
    updated_time = models.DateTimeField(auto_now=True)
#

View:-

class ViolationCreateView(generics.CreateAPIView):
    queryset = Violation.objects.all()
    serializer_class = ViolationSerializer

    def create(self, request, *args, **kwargs):
        # Extract files from request.FILES and add them to the request data
        evidence_files = request.FILES.getlist('evidence_set')
        
        data = request.data.copy()
        if evidence_files:
            data.setlist('evidence_set', [{'evidence': file} for file in evidence_files])

        # Initialize the serializer with the updated data
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)

        # Save the validated data
        self.perform_create(serializer)
        
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
#

I have 0 idea why the violation isn't getting created and there's an error that evidence_set field is not set.

muted wing
#

What is precise error?

winter galleon
muted wing
#

I would probably be overriding to_internal_value on the main serializer at this point and dumping print statements to understand what is going on.

winter galleon
#

Like I am sending data via FormData not normal json.

The files are in request.files and their name is evidence_set

#

I think that's causing the problem

winter galleon
#

Please help

warped swan
#

Hi @winter galleon , I got your issue,

What you are to do it introduce the right parser.

By default Django Rest has the json as parser

REST_FRAMEWORK = {
    #...
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
    ]
    #...
}

So for any class where you need a multifom data form, You will need to mention it.

This way:

# ... code
+ from rest_framework.parsers import MultiPartParser, FormParser

class ViolationCreateView(generics.CreateAPIView):
+   parser_classes = [MultiPartParser, FormParser]
    queryset = Violation.objects.all()
    serializer_class = ViolationSerializer

    def create(self, request, *args, **kwargs):
        # Extract files from request.FILES and add them to the request data
        evidence_files = request.FILES.getlist('evidence_set')
        
        data = request.data.copy()
        if evidence_files:
            data.setlist('evidence_set', [{'evidence': file} for file in evidence_files])

        # Initialize the serializer with the updated data
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)

        # Save the validated data
        self.perform_create(serializer)
        
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

🙂 Fell free to pin me if an issue happens.

winter galleon
winter galleon
# warped swan Hi <@814444216042127400> , I got your issue, What you are to do it introduce th...

"evidence_set": [
"This field is required."
]

Still 🥲

The frontend logs

Form validated and saved
File added: default_avatar.jpeg
Request fields: {student_name: ededede, parent_id: dedede, subject: Science, department: Department 2, grade: 9, teacher: Teacher 1, deputy_hod: Deputy HOD 3, hod: HOD 2,
compliance_analyst_id: dededed, description: deded, violation_type: homework, title: ded}
Request files: default_avatar.jpeg

I will switch to base 64 and just upload via JSON. Formdata doesn't work

winter galleon
#

It's fixed now, when I used base64 for multifile upload