iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
自我挑戰組

轉職新手學 Django 及 DRF系列 第 27

Day 27 - 製作 API (六) 完成 Book API 功能

  • 分享至 

  • xImage
  •  

做完了端點,接下來會把功能部分完成。

BookDetailSerializer

這邊會新增一個BookDetailSerializer,在其中除了包含BookSerilizer中的欄位外還會將description的欄位加入,因此獨立做一個 serializer 出來。到 book/serializer.py 中新增:

# ...
class BookDetailSerializer(BookSerializer):
    """Serializer for book detail view."""

    class Meta(BookSerializer.Meta):
        fields = BookSerializer.Meta.fields + ['description']

這邊直接繼承自 BookSerializer,而class Meta也同樣繼承自 BookSerializer。

class Meta的繼承語法比較特別,需要注意。
儲存後到 book/views.py 中修改原本的程式碼並新增:

# ...
class BookViewSet(viewsets.ModelViewSet):
    """View for manage book APIs."""
    serializer_class = serializers.BookDetailSerializer # 這邊改為 BookDetailSerializer
    queryset = Book.objects.all()
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

    # ...
    def get_serializer_class(self):
        """Return the serializer class for request."""
        if self.action == 'list':
            return serializers.BookSerializer

        return self.serializer_class

此處的函式會覆寫原本存在於ModelViewSet中的預設函式,並將預設的serializer_class設定為 BookDetailSerializer,因大多操作(如 create, update, delete)都會使用到 Book model 的所有欄位;而當 action 為 list 時才會使用BookSerializer,也就會回傳不包含 description 的所有 Book list。延伸閱讀

除了這個函式之外,創建的函式也需要被覆寫,因為我們想讓創建物件的 user 與 object 產生關聯,而原本預設的創建函式沒有此設定。在BookViewSet的下方再加入此函式:

# ...
class BookViewSet(viewsets.ModelViewSet):
    # ...
    def perform_create(self, serializer):
        """Create a new book."""
        serializer.save(user=self.request.user)

以下幾種情況可能會需要像上面一樣製作另一個獨立的 serializer:

  • 額外的欄位
  • 不同驗證方式
  • 不同的行為

完成後,可以再次啟動伺服器測試看看,所有的端點應該都能回傳正確的回應。

這邊請求的Request body使用application/json

結語

如此一來,目前 books API 端點的功能都完成了。在製作只有使用 CRUD 的 API 時使用 viewset 搭配 DefaultRouter 是個相當方便快速的工具。接下來會著手製作圖片的上傳功能,明天見~


上一篇
Day 26 - 製作 API (五) Book model 相關
下一篇
Day 28 - 中場暫停(四) Python 及 Django 的圖片處理
系列文
轉職新手學 Django 及 DRF30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言