Django REST Framework:响应中缺少序列化程序字段

Django REST Framework:响应中缺少序列化程序字段,django,django-rest-framework,Django,Django Rest Framework,我正在使用Django 2.0和Django REST框架 我有两种型号contact和transaction,如下所示 联系方式 class Contact(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=

我正在使用
Django 2.0
Django REST框架

我有两种型号
contact
transaction
,如下所示

联系方式

class Contact(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100, blank=True, null=True)
class AmountGiven(models.Model):
    contact = models.ForeignKey(Contact, on_delete=models.PROTECT)
    amount = models.FloatField(help_text='Amount given to the contact')
    interest_rate = models.FloatField(blank=True, default=None, null=True, help_text='% of interest to be calculated')
    _given_date = models.DateTimeField(
        db_column='given_date',
        default=timezone.now,
        help_text='Date and time when amount was given to the contact'
    )

    def __str__(self):
        return str(self.amount)

    @property
    def given_date(self):
        return self._given_date

    @given_date.setter
    def given_date(self, value):
        self._given_date = value

    @property
    def interest_to_pay(self):
        if self.interest_rate:    
            datetime_diff = datetime.now(get_localzone()) - self.given_date
            days = datetime_diff.days
            duration_in_year = days/365

            simple_interest_amount = (self.amount * duration_in_year * self.interest_rate)/100

            return simple_interest_amount

        return 0

    @property
    def total_payable(self):
        return self.amount + self.interest_to_pay

    @property
    def amount_due(self):
        returned_amount = 0
        for returned in self.amountreturned_set.all():
            returned_amount += returned.amount

        return self.total_payable - returned_amount
给定型号的金额

class Contact(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100, blank=True, null=True)
class AmountGiven(models.Model):
    contact = models.ForeignKey(Contact, on_delete=models.PROTECT)
    amount = models.FloatField(help_text='Amount given to the contact')
    interest_rate = models.FloatField(blank=True, default=None, null=True, help_text='% of interest to be calculated')
    _given_date = models.DateTimeField(
        db_column='given_date',
        default=timezone.now,
        help_text='Date and time when amount was given to the contact'
    )

    def __str__(self):
        return str(self.amount)

    @property
    def given_date(self):
        return self._given_date

    @given_date.setter
    def given_date(self, value):
        self._given_date = value

    @property
    def interest_to_pay(self):
        if self.interest_rate:    
            datetime_diff = datetime.now(get_localzone()) - self.given_date
            days = datetime_diff.days
            duration_in_year = days/365

            simple_interest_amount = (self.amount * duration_in_year * self.interest_rate)/100

            return simple_interest_amount

        return 0

    @property
    def total_payable(self):
        return self.amount + self.interest_to_pay

    @property
    def amount_due(self):
        returned_amount = 0
        for returned in self.amountreturned_set.all():
            returned_amount += returned.amount

        return self.total_payable - returned_amount
ContactSerializer

class ContactSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedRelatedField(
        view_name='contacts:detail',
        read_only=True
    )

    user = serializers.CurrentUserDefault()

    amount_due = ReadOnlyField(source='amountgiven__amount_due')

    class Meta:
        model = Contact
        fields = ('url', 'id', 'first_name', 'last_name', 'full_name', 'amount_due')
并在视图中.py

class ContactViewSet(viewsets.ModelViewSet):
    serializer_class = ContactSerializer
    permission_classes = (IsAuthenticated, AdminAuthenticationPermission,)

    def get_queryset(self):
        return Contact.objects.filter(user=self.request.user)

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

但是在使用
GET
方法向
/contacts/
端点发出请求时返回的响应中没有
amount\u due
url
字段。

您的建模不允许您以想要的方式访问amount\u due

您的
联系人
型号没有
amountgiven
属性。 但是,它确实有
amountgived\u集
,您可以使用该集获取给定联系人的amountgived查询集

但是可以有多个,因此您需要决定要在序列化程序中显示哪个
到期金额

您可以使用
SerializerMethodField
序列化您想要的到期金额的值:

class ContactSerializer(serializers.HyperlinkedModelSerializer):
    amount_due = serializers.SerializerMethodField()

    def get_amount_due(self, obj):
         amountgiven = obj.amountgiven_set.first()
         return amountgiven.amount_due
但是,正如我已经提到的那样,amountgiven_set返回一个查询集,其中可以有多个对象


如果您确定给定联系人只有一个,您可以使用我的示例中的
first()
来获取它。

您的建模不允许您以您希望的方式访问到期金额

您的
联系人
型号没有
amountgiven
属性。 但是,它确实有
amountgived\u集
,您可以使用该集获取给定联系人的amountgived查询集

但是可以有多个,因此您需要决定要在序列化程序中显示哪个
到期金额

您可以使用
SerializerMethodField
序列化您想要的到期金额的值:

class ContactSerializer(serializers.HyperlinkedModelSerializer):
    amount_due = serializers.SerializerMethodField()

    def get_amount_due(self, obj):
         amountgiven = obj.amountgiven_set.first()
         return amountgiven.amount_due
但是,正如我已经提到的那样,amountgiven_set返回一个查询集,其中可以有多个对象


如果您确定给定联系人只有一个,您可以使用我的示例中的
first()
来获取它。

根据您的评论,您需要所有金额的总和(请编辑您的问题)。因此,您应该在查询集中使用注释:

from django.db.models import Sum

def get_queryset(self):
    return Contact.objects.filter(user=self.request.user).annotate(amount_due=Sum('amountgiven_set__amount'))
(我建议对查询集和筛选使用modelManager,而不是在此处执行此操作)

并在序列化程序中添加如下字段:

amount_due = serializer.IntegerFiled()

根据您的评论,您需要所有金额的总和(请编辑您的问题)。因此,您应该在查询集中使用注释:

from django.db.models import Sum

def get_queryset(self):
    return Contact.objects.filter(user=self.request.user).annotate(amount_due=Sum('amountgiven_set__amount'))
(我建议对查询集和筛选使用modelManager,而不是在此处执行此操作)

并在序列化程序中添加如下字段:

amount_due = serializer.IntegerFiled()

实际上,没有
到期金额
列,是的,对于单个
联系人
,给定的
金额
可以有多条记录。我只是把给联系人的所有金额加起来,以返回到期金额。那么,我应该使用
ModelManager
方法而不是model方法吗?您可以在序列化程序中对其进行总结。在我的示例中,您可以使用serializerMethodField并在该方法中执行它。但我喜欢这个问题的另一个答案中的方法。因此,请看这一个。使用
ModelManager
返回模型中所有
amount\u due
的总和,因为用户可能有许多记录,并且模型类中的
amount\u due
正在基于实体计算特定实体的到期金额。实际上没有
amount\u due
列,是的对于一个
联系人
给定的
金额
可以有多个记录。我只是把给联系人的所有金额加起来,以返回到期金额。那么,我应该使用
ModelManager
方法而不是model方法吗?您可以在序列化程序中对其进行总结。在我的示例中,您可以使用serializerMethodField并在该方法中执行它。但我喜欢这个问题的另一个答案中的方法。因此,请看这一个。使用
ModelManager
返回模型中所有
amount\u due
的总和,因为用户可能有许多记录,并且模型类中的
amount\u due
正在基于实体计算特定实体的到期金额。