获取Django Rest API的第一个和最后一个相关对象

vq8itlhq  于 2022-11-26  发布在  Go
关注(0)|答案(1)|浏览(126)

我有基于2个模型的Django Rest API序列化器,Book和Chapter

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字段
Chapter模型有一个Book的外键。
我尝试了类似下面的东西,以获得最后一章

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。

a6b3iqyw

a6b3iqyw1#

您可以使用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

相关问题