Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass additional keyword arguments in a custom Field in Django Rest Framework?

I'm using Django Rest Framework and want to create a custom Field to use in my serializers.

class PivotField(serializers.Field):
    def __init__(self, *args, **kwargs):
        self.key_attr   = kwargs.get('key_attr')
        self.value_attr = kwargs.get('value_attr')
        super(PivotField, self).__init__(*args, **kwargs)

    def to_representation(self, value):
        data = {}
        for model in value.all():
            # this is where I'd use the key_attr and value_attr
            data[model.type.name] = model.uri
        return data

I'd like to be able to pass additional arguments to the field like this.

resources = PivotField(key_attr='type.name', value_attr='uri')

However, I keep getting the following error.

TypeError: init() got an unexpected keyword argument 'key_attr'

Is there some way to register these as valid kwargs within the field?

like image 264
Soviut Avatar asked May 19 '16 14:05

Soviut


1 Answers

A custom field created by subclassing Field class does not accept extra arguments using **kwargs option in __init__() method. You should override the __init__() method in PivotField and pop those extra arguments after setting them on the instance.

DRF source code for __init__() method in Field class:

class Field(object):

    def __init__(self, read_only=False, write_only=False,
                 required=None, default=empty, initial=empty, source=None,
                 label=None, help_text=None, style=None,
                 error_messages=None, validators=None, allow_null=False):
       ...

We can see from above that there is no option for sending extra arguments other than the defined keyword arguments.

So, you should pop those extra arguments from kwargs while setting them on instance.

class PivotField(serializers.Field):
    def __init__(self, *args, **kwargs):
        self.key_attr = kwargs.pop('key_attr', None) # pop the custom kwarg
        self.value_attr = kwargs.pop('value_attr', None) # pop the custom kwarg
        super(PivotField, self).__init__(*args, **kwargs)
like image 102
Rahul Gupta Avatar answered Sep 20 '22 11:09

Rahul Gupta