Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DRF How to patch when file upload is required...?

DRF How do you patch when file upload is required and you don't want to post the file again?

I keep getting this response: {'xyz_file': [u'No file was submitted.']}

I don't have xyz_file required on the serializer. This is not a field on the model because I don't want to save it in the db.

class XYZSerializer(ParentSerializer):
    xyz_file = serializers.FileField(source='get_file_field', use_url=False, validators=[xyz_extensions_validator])

    class Meta:
        model = models.XYZModel
        fields = ('name', 'xyz_file', 'active',)

I've tried overwriting the update method in the view and serializer. Neither worked.

like image 202
Chris Avatar asked Oct 15 '25 10:10

Chris


2 Answers

Ok so this is how i fixed my problem.

In my serializer I added this method:

def exclude_fields(self, fields_to_exclude=None):
    if isinstance(fields_to_exclude, list):
        for f in fields_to_exclude:
            f in self.fields.fields and self.fields.fields.pop(f) or next()

In my viewset I overrode the update method with this:

def update(self, request, *args, **kwargs):
    partial = False
    if 'PATCH' in request.method:
        partial = True
    instance = self.get_object()
    serializer = self.get_serializer(instance, data=request.data, partial=partial)
    if 'xyz_file' in request.data and not request.data['xyz_file']:
        serializer.exclude_fields(['xyz_file'])
    if not serializer.is_valid():
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    serializer.save()
    return Response(serializer.data)

So the idea is to remove the field from even being validated. Also if you wanted to run this on a field that is on the model, the popping of the field will prevent you from saving the non validated field.

like image 52
Chris Avatar answered Oct 18 '25 08:10

Chris


If you are using PATCH HTTP method, then you could turn on partial updates, which doesnt require any fields I believe.

Then you define your serializer inside your update method in your view:

serializer = XYZSerializer(instance=xyz,data=request.data,partial=True)

Is written here http://www.django-rest-framework.org/api-guide/serializers/#partial-updates.

like image 42
Matúš Bartko Avatar answered Oct 18 '25 08:10

Matúš Bartko