DRF ListAPIView return manytomany 值名称而不是 pk

DRF ListAPIView return manytomany value names instead of pk

我有一个 Post 模型包含标签字段,该字段具有 ManyToManyField 类别模型,

当我调用 REST ListAPIView all post tags returns in pk 我试图覆盖 ListAPIView 中的列表函数并为每个 post 映射所有 tags_names 但这会花费大量时间并破坏性能

我 hope/Believe 为这种情况内置了一些东西

models.py

class Post(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=256)
    content = RichTextField()
    tags = models.ManyToManyField(Categories)

    def __str__(self):
        return self.title



class Categories(models.Model):
    tag_name = models.CharField(max_length=256, unique=True)

    def __str__(self):
        return self.tag_name

    class Meta:
        ordering = ('tag_name',)
        unique_together = ('tag_name',)

views.py

from .models import Post
from .serializers import NewPostSerializer, PostSerializer


class NewPost(CreateAPIView):
    serializer_class = NewPostSerializer
    permission_classes = [IsAuthenticated, IsAdminUser]


class PostList(ListAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

serializers.py

class NewPostSerializer(ModelSerializer):

    class Meta:
        model = Post
        fields = ['title', 'content', 'tags']

        read_only_fields = ['tags', 'author_id']

当我访问 ListApiView link 时返回的结果是这样的:

[
    {
        "id": 30,
        "title": "post title test",
        "content": "lorem text",
        "author": 3,
        "tags": [
            8, # should be games
            3  # should be action
        ]
    }
]

要优化性能,您应该使用 prefetch_related。这将对您的数据库的查询数量减少到只有 1 个请求来获取您所有帖子的所有相关标签。

class PostList(ListAPIView):
    queryset = Post.objects.prefetch_related('tags').all()
    serializer_class = NewPostSerializer

现在要对标签进行序列化,您必须创建一个新的序列化程序。

class TagSerializer(ModelSerializer):

    class Meta:
        model = Categories
        fields = ['name']

然后您可以在 NewPostSerializer.

中使用此序列化程序
class NewPostSerializer(ModelSerializer):
    tags = TagSerializer(many=True, read_only=True)

    class Meta:
        model = Post
        fields = ['title', 'content', 'tags']

        read_only_fields = ['author_id']

这个结果应该是"tags": [{"name": "ABC"},{"name": "EFG"}]

您可以简单地使用 SlugRelatedField,这将 return 名称列表而不是 pks 列表

from rest_framework import serializers
class NewPostSerializer(ModelSerializer):

    tags = serializers.SlugRelatedField(
        many=True,
        read_only=True,
        slug_field='tag_name'
    )
    class Meta:
        model = Post
        fields = ['title', 'content', 'tags']

        read_only_fields = ['author_id']