Django Rest Framework 如何序列化关系模型?

Django Rest Framework how to serialize a relational Model?

我正在学习 Django Rest Framework 并成功创建了一些 APIs。现在我正在尝试序列化一个关系,但我不知道它是如何工作的。这是我的代码:

class Countries(models.Model):
    country = models.CharField(max_length=255)

    class Meta:
        managed = False
        db_table = 'countries'

class Users(models.Model):
    name = models.CharField(max_length=255)
    email = models.CharField(max_length=255)
    country = models.ForeignKey(Countries, models.DO_NOTHING)
    date = models.DateTimeField()

    class Meta:
        managed = False
        db_table = 'users' 

在views.py

def get(self,request):
        print(UsersSerializer)
        users = Users.objects.all()
        serializer = UsersSerializer(users,many = True)
        return Response(serializer.data)

序列化器:

class UsersSerializer(serializers.ModelSerializer):
    class Meta:
        model = Users
        fields = '__all__'

当我 运行 API 我得到

[
  {
    "id": 3,
    "name": "dsadasd",
    "email": "dasd@gmail.com",
    "date": "2020-05-12T12:15:24Z",
    "country": 1
  }
]

在国家/地区字段中,我正在获取国家/地区 id,我期待这里的国家/地区名称...

您需要将您的 UsersSerializer 更改为 return 国家名称而不是 ID。

class UsersSerializer(serializers.ModelSerializer):
    <b>country = serializers.SerializerMethodField()</b>  # add this line

    class Meta:
        model = Users
        fields = '__all__'

    <b>def get_country(self, instance):
        return instance.country.country</b>  # return country name

进一步阅读 SerializerMethodField

您可以使用 source 字段参数来检索 country 而不是 id:

... or may use dotted notation to traverse attributes, such as EmailField(source='user.email'). When serializing fields with dotted notation, it may be necessary to provide a default value if any object is not present or is empty during attribute traversal.

因此您的序列化程序应该如下所示:

class UsersSerializer(serializers.ModelSerializer):
    country = serializers.CharField(source='country.country', default='')

    class Meta:
        model = Users
        fields = ('id', 'name', 'email', 'date', 'country')
        # You may use fields='__all__' but I find the explicit declaration 
        # more flexible.