如何使用 django rest 在嵌套的 Serializer 上调用实例方法?

How to call instance methods on the nested Serializer with django rest?

我有两个模型要嵌套在一起。 TimesheetInvoice

我的 InvoiceSerializer 看起来像这样:

class InvoiceSerializer(serializers.ModelSerializer):

    billable_timesheets = serializers.SerializerMethodField() 
    total_hours_and_cost = serializers.SerializerMethodField() 

    class Meta:
        model = Invoice
        fields = (
            "hours",
            "hour_cost",
            "billable_timesheets",
            "total_hours_and_cost", 
            ...

            )

    def get_total_hours_and_cost(self, obj):
        return obj.hours * obj.hour_cost

    def get_billable_timesheets(self, obj):
        """Getting all timesheets for selected billable period"""
        timesheets = obj.project.timesheets.filter(<queryset here>)
        return TimesheetSerializer(timesheets, many=True).data

一切正常 - 我可以定义 MethodFields 并返回正确的 JSON,太棒了。但是,我在我的子模型(在本例中为 Timesheet 模型)上获得了一个方法,我需要访问该方法并运行 进行一些计算。我正在通过 get_billable_timesheets 获取必要的数据,现在我需要 运行 在我的 Timesheet model 上调用一个名为 total_duration() 的方法。每当我尝试按照

的方式做某事时
timesheets = self.get_billable_timesheets(obj)
hours = 0
for timesheet in timesheets:
    hours += timesheet.total_duration()

我得到: AttributeError: 'collections.OrderedDict' object has no attribute 'total_duration'

我不明白的是,我实际上已经通过 get_billable_timesheets 方法序列化了数据 - 为什么我仍然收到此错误?

for 循环中的时间表是一个有序的 dict 实例,因为 get_billable_timesheets returns 序列化数据。

解决方法是,

timesheets = self.get_billable_timesheets(obj)
hours = 0
for timesheet in timesheets:
    timesheet_id = timesheet.get('id')
    timesheet_obj = Timesheet.objects.get(id=timesheet_id)
    hours += timesheet_obj.total_duration()

我的案例的一个可行解决方案是不 return 时间表的序列化版本,(例如,而不是 return TimesheetSerializer(timesheets, many=True).data

我刚刚做了 return timesheets → 做了我的计算需要然后序列化时间表:

    def get_billable_timesheets(self, obj):
        """Getting all timesheets for selected billable period"""
        timesheets = obj.project.timesheets.filter(<queryset here>)
        return timesheets # instead of a serialized version