whoisearth
whoisearth

Reputation: 4160

django rest framework serializer exclude field completely

I have data I'm trying to PUT into the database and it includes a field that I want to use to generate data for another field. I'm completely confused as to how to get my serializer to ignore the but still use obj.owner_name to get the owner_id to use for the PUT.

If anyone can point me to what I'm doing wrong that would be great.

<root>
  <list-item>
    <varmst_id>1867</varmst_id>
    <varmst_type>3</varmst_type>
    <varmst_name>var_date                      </varmst_name>
    <varmst_value>20140911</varmst_value>
    <varmst_desc/>
    <varmst_public>Y</varmst_public>
    <owner_name>Operations</owner_name>
  </list-item>
</root>

Here is my serializer -

class VariablePUTSerializer(serializers.ModelSerializer):
    owner_id = serializers.SerializerMethodField('get_owner_id')

    class Meta:
        model = Varmst
        resource_name = 'varmst'
        fields = ('varmst_id', 'varmst_type', 'varmst_name', 'varmst_value', 'varmst_desc',
                'varmst_public', 'owner_id')
        exclude_fields = ('owner_name',)

    def transform_varmst_id(self, obj, value):
        maxid = Varmst.objects.latest('varmst_id').varmst_id
        if Varmst.objects.filter(varmst_name=obj.varmst_name).exists():
            obj.varmst_id = Varmst.objects.filter(varmst_name=obj.varmst_name).values_list('varmst_id')[0]
            return obj.varmst_id
        else:
            obj.varmst_id = maxid + 1
            return obj.varmst_id

    def get_owner_id(self, obj):
        obj.owner_id = Owner.objects.filter(owner_name=obj.owner_name).values_list('owner_id')[0]
        return obj.owner_id

This is my traceback when I try to do a PUT with the data above -

Traceback:
File "D:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
  112.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "D:\Python27\lib\site-packages\django\views\generic\base.py" in view
  69.             return self.dispatch(request, *args, **kwargs)
File "D:\Python27\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
  57.         return view_func(*args, **kwargs)
File "D:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
  400.             response = self.handle_exception(exc)
File "D:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
  397.             response = handler(request, *args, **kwargs)
File "D:\Tidal\API\views.py" in put
  343.             return Response(serializer.data, status=status.HTTP_201_CREATED)
File "D:\Python27\lib\site-packages\rest_framework\serializers.py" in data
  573.                 self._data = [self.to_native(item) for item in obj]
File "D:\Python27\lib\site-packages\rest_framework\serializers.py" in to_native
  351.             value = field.field_to_native(obj, field_name)
File "D:\Python27\lib\site-packages\rest_framework\fields.py" in field_to_native
  1035.         value = getattr(self.parent, self.method_name)(obj)
File "D:\Tidal\API\serializers.py" in get_owner_id
  163.         obj.owner_id = Owner.objects.filter(owner_name=obj.owner_name).values_list('owner_id')[0]

Exception Type: AttributeError at /deploy/variable/
Exception Value: 'Varmst' object has no attribute 'owner_name'

I know 'Varmst' doesn't have a table called 'owner_name'. Just because the serializer has it doesn't mean I'm going to use it....

Upvotes: 0

Views: 2943

Answers (1)

cezar
cezar

Reputation: 12012

You could make your method transform_varmst_id more pythonic:

def transform_varmst_id(self, obj, value):
    maxid = Varmst.objects.latest('varmst_id').varmst_id
    if Varmst.objects.filter(varmst_name=obj.varmst_name).exists():
        obj.varmst_id = Varmst.objects.filter(varmst_name=obj.varmst_name).values_list('varmst_id')[0]
    else:
        obj.varmst_id = maxid + 1
    return obj.varmst_id

There is no need for multiple return statements in this particular case.

EDIT:

No need to create the variable maxid every time the method is called. Put that within the condition:

def transform_varmst_id(self, obj, value):
    if Varmst.objects.filter(varmst_name=obj.varmst_name).exists():
        obj.varmst_id = Varmst.objects.filter(varmst_name=obj.varmst_name).values_list('varmst_id')[0]
    else:
        maxid = Varmst.objects.latest('varmst_id').varmst_id
        obj.varmst_id = maxid + 1
    return obj.varmst_id

That's more pythonic. You could certainly reduce the else block to:

obj.varmst_id = Varmst.objects.latest('varmst_id').varmst_id + 1

but that's matter of taste. I prefer shorter statements, vertical is better than horizontal.

Upvotes: 2

Related Questions