在 Django 序列化器中作为源执行函数

phy*_*ion 4 django serialization python-3.x

我有以下型号:

class A(Model):
    pass

class B(Model):
    a = ForeignKey(A, related_name = 'b')
    b_field = CharField(max_length=64)
Run Code Online (Sandbox Code Playgroud)

我现在想要序列化一个 A 对象,其中我想要第一个 b 对象。我曾经有这样的代码:

class BSerializer(ModelSerializer):

    class Meta:
        model = B
        fields = '__all__'

class ASerializer(ModelSerializer):
    b = BSerializer(source='b.first')

    class Meta:
        model = A
        fields = '__all__'
Run Code Online (Sandbox Code Playgroud)

这曾经有效,但现在我的单元测试失败了:

AttributeError: Got AttributeError when attempting to get a value for field `b_field` on serializer `BSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `method` instance.
Original exception text was: 'function' object has no attribute 'b_field'.
Run Code Online (Sandbox Code Playgroud)

显然,b.first是一个函数,而 that 确实没有这样的属性。但是我想要源字段来执行该函数。我尝试了以下行:

    b = BSerializer(source='b.first')
Run Code Online (Sandbox Code Playgroud)

但这却遇到了以下错误:

AttributeError: Got AttributeError when attempting to get a value for field `b` on serializer `ASerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `A` instance.
Original exception text was: 'RelatedManager' object has no attribute 'first()'.
Run Code Online (Sandbox Code Playgroud)
  1. 这种行为最近有改变吗?
  2. 如何获取 a 中的第一个 b 对象进行序列化?

tri*_*het 6

周围的规格source没有改变,您可以在文档中阅读:

source:将用于填充字段的属性的名称。可能是只接受 self 参数的方法,例如URLField(source='get_absolute_url'),或者可以使用点分符号来遍历属性,例如EmailField(source='user.email')

因此,您应该传递正在序列化实例的类的attr 或方法名称(在您的情况下)A,或者传递 attr 或方法来遍历属性(使用点表示法),但始终从类的 attr/方法开始A

因此,您可以这样解决您的问题:

class A(Model):
    def first_b(self):
        return self.b.first()


class ASerializer(ModelSerializer):
    b = BSerializer(source='first_b')

    class Meta:
        model = A
        fields = '__all__
Run Code Online (Sandbox Code Playgroud)