使用Django開發REST接口
我們以在Django框架中使用的圖書以及書中人物案例來寫一套支持圖書數據增刪改查的REST API接口,來理解REST API的開發(前后端均發送JSON格式數據)
路由代碼(urls.py):
urlpatterns = [ path('books/', views.BookListView.as_view()), re_path('books/(?P<pk>\d+)/', views.BookDetailView.as_view()) ]
views.py:

from datetime import datetime from django.http import JsonResponse,HttpResponse import json class BookListView(View): """ 查詢所有的書籍、增加書籍 """ def get(self,request): """ 查詢所有的書籍, 路由:GET /books/ :param request: :return: """ queryset = BookInfo.objects.all() book_list = [] for book in queryset: book_list.append({ "id":book.id, "btitle":book.title, "bpub_date":book.pub_date, "bread":book.read, "bcommet":book.comment, "image":book.image.url if book.image else "" }) #為了不使字典的數據發送,將參數safe變為False return JsonResponse(book_list,safe=False) def post(self,request): """ 新增書籍 路由:POST/books/ :param request: :return: """ json_bytes = request.body json_str = json_bytes.decode() #將字符串對象反序列化 book_dict = json.loads(json_str) ################################ book = BookInfo.objects.create( title = book_dict.get("btitle"), pub_date = book_dict.get("bpub_date") #.....................省略其他參數 ) #返回插入的數據,以json格式返回,並且帶上狀態碼 return JsonResponse({ "id":book.id, "btitle":book.title, 'bpub_date': book.pub_date, 'bread': book.read, 'bcomment': book.comment, 'image': book.image.url if book.image else '' },status=201) class BookDetailView(View): def get(self,request,pk): """ 獲取單個圖書信息 路由:GET/books/<pk>/ :param request: :param pk: :return: """ try: book = BookInfo.objects.get(pk=pk) except BookInfo.DoesNotExist: return HttpResponse(status=404) return JsonResponse({ "id": book.id, "btitle": book.title, 'bpub_date': book.pub_date, 'bread': book.read, 'bcomment': book.comment, 'image': book.image.url if book.image else '' }) def put(self,request,pk): """ 修改圖書信息 路由:PUT/books/<pk>/ :param request: :param pk: :return: """ try: book = BookInfo.objects.get(pk=pk) except BookInfo.DoesNotExist: return HttpResponse(status=404) json_bytes = request.body json_str = json_bytes.decode() book_dict = json.loads(json_str) ##########此處詳細的校驗參數省略############# book.title = book_dict.get('btitle') book.pub_date = book_dict.get('bpub_date') book.save() return JsonResponse({ "id": book.id, "btitle": book.title, 'bpub_date': book.pub_date, 'bread': book.read, 'bcomment': book.comment, 'image': book.image.url if book.image else '' }) def delete(self,request,pk): """ 刪除圖書 路由:DELETE/books/<pk>/ :param request: :param pk: :return: """ try: book = BookInfo.objects.get(pk=pk) except BookInfo.DoesNotExist: return HttpResponse(status=404) book.delete() return HttpResponse(status=204)
測試:
使用Postman軟件測試接口
1、獲取所有圖書信息
GET方式訪問http://127.0.0.1:8000/books/,返回狀態碼200以及json數據
2、獲取單一的圖書數據
GET 訪問 http://127.0.0.1:8000/books/5/ ,返回狀態碼200以及json數據
3、新增書籍信息
POST訪問http://127.0.0.1:8000/books/,發送json數據,返回json數據以及狀態碼
4、修改書籍數據
PUT訪問http://127.0.0.1:8000/books/2/,發送json數據,返回json數據以及狀態碼
5、刪除書籍數據
DELETE訪問http://127.0.0.1:8000/books/2/,發送json數據,返回狀態碼204
2、明確REST接口開發的核心任務
在上面的案例中,在開發REST API接口時候,視圖主要做的三件事:
1、將請求的數據(如json格式)轉化為模型類對象
2、操作數據庫(增刪改查)
3、將模型類對象轉換為響應的數據(如json數據格式)
序列化(Serialization)
就是將程序中的一個數據結構類型轉化為其他格式(字典、json、XML等)。例如在Django中的模型類對象轉換為JSON字符串,這就是序列化(json.dumps())。
反之,將其他數據(字典、json、XML等)轉化為程序的數據,例如將JSON字符串轉換為Django中的模型類對象,這個過程就叫反序列化(json.load())
在開發REST API時,視圖中要頻繁的進行序列化與反序列化。
總結:
在開發REST API接口,在視圖中需要做的核心就是:1、將數據庫數據序列化(json.dumps())為前端所需要的格式,並返回。2、將前端發送的數據反序列化(json.load())為模型類對象,保存在數據庫中。
Django REST framework介紹:
在序列化與反序列化時,雖然操作的數據不盡相同,但是執行的過程卻是相似的,也就是說這部分代碼是可以復用簡化編寫的。
在開發REST API的視圖中,雖然每個視圖具體操作的數據不同,但增、刪、改、查的實現流程基本套路化,所以這部分代碼也是可以復用簡化編寫的:
- 增:校驗請求數據 -> 執行反序列化過程 -> 保存數據庫 -> 將保存的對象序列化並返回
- 刪:判斷要刪除的數據是否存在 -> 執行數據庫刪除
- 改:判斷要修改的數據是否存在 -> 校驗請求的數據 -> 執行反序列化過程 -> 保存數據庫 -> 將保存的對象序列化並返回
- 查:查詢數據庫 -> 將數據序列化並返回
Django REST framework可以幫助我們簡化上述兩部分的代碼編寫,大大提高REST API的開發速度。Django REST framework 框架是一個用於構建Web API 的強大而又靈活的工具。通常簡稱為DRF框架 或 REST framework。DRF框架是建立在Django框架基礎之上,由Tom Christie大牛二次開發的開源項目。
特點
- 提供了定義序列化器Serializer的方法,可以快速根據 Django ORM 或者其它庫自動序列化/反序列化;
- 提供了豐富的類視圖、Mixin擴展類,簡化視圖的編寫;
- 豐富的定制層級:函數視圖、類視圖、視圖集合到自動生成 API,滿足各種需要;
- 多種身份認證和權限認證方式的支持;
- 內置了限流系統;
- 直觀的 API web 界面;
- 可擴展性,插件豐富