DRF - 'ServersSerializer'对象没有属性'attr_name' - 调用外部SerializerMethodField

时间:2015-12-31 16:37:44

标签: django django-rest-framework

我正在尝试抽象出SerializerMethodField但没有成功。

这是我目前在serializers.py

中的内容
class ServersSerializer(serializers.ModelSerializer):
    bmccode = serializers.SerializerMethodField('get_bmc')

    def get_bmc(self, obj):
        code = Tblbmcgroups.objects.filter(groupid = obj.recordownerid).values_list('bmccode')[0][0]
        return code

    app_name = serializers.SerializerMethodField('get_app')

    def get_app(self, obj):
        code = Tblapplicationserverlinks.objects.filter(serverid=obj.id).values_list(
            'applicationid__name', flat=True).distinct()
        return code

    class Meta:
        model = Servers
        fields = ('id', 'name', 'isvirtual', 'locationid', 'managedbyid', 'operatingsystem', 'model',
                  'assettag', 'inceptiondate', 'comments', 'assetstatusid', 'recordownerid', 'lastmodifieddate',
                  'lastmodifiedby', 'app_name', 'bmccode')
        depth = 1

上面的工作,但我想要的是一个脚本/ joined_data.py文件,其中包含以下内容 -

    def get_bmc(self, obj):
        code = Tblbmcgroups.objects.filter(groupid = obj.recordownerid).values_list('bmccode')[0][0]
        return code

这样代码可以被其他序列化程序使用。问题是在我的serializers.py

中执行此操作
class ServersSerializer(serializers.ModelSerializer):
    bmccode = serializers.SerializerMethodField('get_bmc')

    app_name = serializers.SerializerMethodField('get_app')

    def get_app(self, obj):
        code = Tblapplicationserverlinks.objects.filter(serverid=obj.id).values_list(
            'applicationid__name', flat=True).distinct()
        return code

    class Meta:
        model = Servers
        fields = ('id', 'name', 'isvirtual', 'locationid', 'managedbyid', 'operatingsystem', 'model',
                  'assettag', 'inceptiondate', 'comments', 'assetstatusid', 'recordownerid', 'lastmodifieddate',
                  'lastmodifiedby', 'app_name', 'bmccode')
        depth = 1

它无法识别序列化程序中不再存在的属性。

我正在做from scripts.joining_data import *

Traceback:
File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Python27\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)
File "C:\Python27\lib\site-packages\rest_framework\viewsets.py" in view
  87.             return self.dispatch(request, *args, **kwargs)
File "C:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
  466.             response = self.handle_exception(exc)
File "C:\Python27\lib\site-packages\rest_framework\views.py" in dispatch
  463.             response = handler(request, *args, **kwargs)
File "C:\Python27\lib\site-packages\rest_framework\mixins.py" in list
  45.             return self.get_paginated_response(serializer.data)
File "C:\Python27\lib\site-packages\rest_framework\serializers.py" in data
  674.         ret = super(ListSerializer, self).data
File "C:\Python27\lib\site-packages\rest_framework\serializers.py" in data
  239.                 self._data = self.to_representation(self.instance)
File "C:\Python27\lib\site-packages\rest_framework\serializers.py" in to_representation
  614.             self.child.to_representation(item) for item in iterable
File "C:\Python27\lib\site-packages\rest_framework\serializers.py" in to_representation
  472.                 ret[field.field_name] = field.to_representation(attribute)
File "C:\Python27\lib\site-packages\rest_framework\fields.py" in to_representation
  1642.         method = getattr(self.parent, self.method_name)

Exception Type: AttributeError at /api/servers/
Exception Value: 'ServersSerializer' object has no attribute 'get_bmc'

2 个答案:

答案 0 :(得分:1)

get_bmc应属于该类。你提取的函数不应该带self参数,因为它不属于任何类。

老实说,我不认为提取单行会在任何时候都能省你,但为了正确起见,这就是你应该做的:

def external_get_bmc(obj):
    return Tblapplicationserverlinks.objects.filter(serverid=obj.id) \
                                            .values_list('applicationid__name', 
                                                         flat=True) \
                                            .distinct()

class ServersSerializer(serializers.ModelSerializer):
    def get_bmc(self, obj):
        return external_get_bmc(obj)

如果您确实只想定义一次,请考虑使用inheritance

答案 1 :(得分:1)

使用mixin模式。像这样:

class BMCMixin(object):
    bmccode = serializers.SerializerMethodField('get_bmc')
    def get_bmc(self, obj):
        code = Tblbmcgroups.objects.filter(groupid=obj.recordownerid).values_list('bmccode')[0][0]
        return code


class ServersSerializer(BMCMixin, serializers.ModelSerializer):
   ... servers specific code ...

您可以将mixin类放入单独的文件中,并在方便时导入它们。