我有基于2个模型的Django REST API序列化程序,书和章

class Book(models.Model):
    title = models.TextField(unique=True)
    description = models.TextField(blank=True, null=True)
    published_at = models.DateTimeField(default=timezone.now, db_index=True)
    added_at = models.DateTimeField(auto_now_add=True, db_index=True)
    modified_at = models.DateTimeField(auto_now=True, db_index=True)

class Chapter(models.Model):
    book = models.ForeignKey(
        Book, on_delete=models.CASCADE,
        related_name='chapters', db_index=True
    )
    published_at = models.DateTimeField(default=timezone.now, db_index=True)
    added_at = models.DateTimeField(auto_now_add=True, db_index=True)
    modified_at = models.DateTimeField(auto_now=True, db_index=True)

在图书序列化程序中,我想要2个自定义字段

  • first_chapter
  • last_chapter

每个对象都具有模型Chapter的对象,您可以从字段名称中了解第一个对象和最后一个对象按published_at字段排序

章节模型有一个外键来预订.

我try 了下面这样的方法来读到最后一章

class LastChapterField(serializers.RelatedField):
    
    def get_queryset(self):
        return core_models.Chapter.objects\
            .filter(book=M.OuterRef("pk"))\
            .select_related("number")\
            .order_by("-published_at")[:1]

但我没有看到我的结果中包括最后一章,尽管在Book Serializer的fields中明确提到了它

我希望返回结果中的完整对象,并且我希望能够对Chapter个模型对象的嵌套字段(first_chapter或last_chapter)之一使用order by.

推荐答案

您可以使用SerializerMethodField来检索您想要的对象,并在其中使用另一个序列化程序:

# serializers.py
from rest_framework import serializers


class ChapterSerializer(serializers.ModelSerializer):

    class Meta:
        model = Chapter
        fields = ('published_at', 'modified_at', 'added_at',)


class BookSerializer(serializers.ModelSerializer):
    first_chapter = serializers.SerializerMethodField()
    last_chapter = serializers.SerializerMethodField()

    def get_first_chapter(self, instance):
        return ChapterSerializer(instance.chapters.order_by('published_at').first()).data

    def get_last_chapter(self, instance):
        return ChapterSerializer(instance.chapters.order_by('published_at').last()).data

    class Meta:
        model = Book
        fields = ('first_chapter', 'last_chapter',
                  [...]  # Add the other fields you want to display here
                 )

然后,您可以在视图中使用序列化程序,例如:

# views.py
from .serializers import BookSerializer
from .models import Book
from rest_framework.generics import RetrieveAPIView


class BookRetrieveView(RetrieveAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

Django相关问答推荐

自定义公钥打破Django管理内联逻辑

仅更新模型中的特定字段.Model Django

django-filter compose 过滤的 url

try 在 django 中发送验证邮箱,出现错误

测试 - 两个类共享相同的登录代码,但它只能在一个类中工作

一次请求中更新整个Django模型

直接在模型类上使用 Django 管理器与静态方法

Django中的左外反向select_related?

URL命名空间的一个真实例子

Django模型字段按变量

Django模板转义

django post_save 更新信号

Django post_save 在不覆盖模型 save() 的情况下防止递归

django 在 unittest 测试中设置环境变量

在 django admin 中链接到外键对象

Table doesn't exist表不存在

显式 cursor.close() 的必要性

Python/Django - 避免在源代码中保存密码

它是如何工作的,Django INSTALLED_APPS 的命名约定?

django.urls.path中name参数的作用是什么?