什麼是RESTful? RESTful是一種開發理念,REST是Roy Thomas Fileding在他博文提出的.REST特點;url簡潔,將參數通過url傳遞到伺服器,簡單就是說URL定位資源,用HTTP動詞描述操作. RESTful架構: 每一個URL代表一種資源; 客戶端和伺服器之間,傳遞 ...
什麼是RESTful?
RESTful是一種開發理念,REST是Roy Thomas Fileding在他博文提出的.REST特點;url簡潔,將參數通過url傳遞到伺服器,簡單就是說URL定位資源,用HTTP動詞描述操作.
RESTful架構:
- 每一個URL代表一種資源;
- 客戶端和伺服器之間,傳遞這種資源的某種表現層;
- 客戶端通過四個HTTP動詞,對伺服器端資源進行操作,實現"表現層狀態轉化"。
- URL節後不能含有動詞
- 一般介面返回的是JSON和XML類型的,JSON一般用的多
- 定義介面統一,使用起來比較方便
RESTful設計方法:
API介面應該部署到專用的功能變數名稱下,如果API不需要擴展,可以放到主功能變數名稱下,API版本號放到URL中或者放到請求頭信息中,路徑就是表示API的具體網站,每個網站都有對應的資源,API中的名詞應該使用複數,
常見的HTTP的動詞
- GET(SELECT):從伺服器取出資源(一項或多項)。
- POST(CREATE):在伺服器新建一個資源。
- PUT(UPDATE):在伺服器更新資源(客戶端提供改變後的完整資源)。
- DELETE(DELETE):從伺服器刪除資源。
不常用的HTTP動詞
- PATCH(UPDATE):在伺服器更新(更新)資源(客戶端提供改變的屬性)。
- HEAD:獲取資源的元數據。
- OPTIONS:獲取信息,關於資源的哪些屬性是客戶端可以改變的。
過濾信息
?limit=10:指定返回記錄的數量 ?offset=10:指定返回記錄的開始位置。 ?page=2&per_page=100:指定第幾頁,以及每頁的記錄數。 ?sortby=name&order=asc:指定返回結果按照哪個屬性排序,以及排序順序。 ?animal_type_id=1:指定篩選條件
常見的狀態碼
- 200 OK - [GET]:伺服器成功返回用戶請求的數據
- 201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。
- 202 Accepted - [*]:表示一個請求已經進入後臺排隊(非同步任務)
- 204 NO CONTENT - [DELETE]:用戶刪除數據成功。
- 400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,伺服器沒有進行新建或修改數據的操作
- 401 Unauthorized - [*]:表示用戶沒有許可權(令牌、用戶名、密碼錯誤)。
- 403 Forbidden - [*] 表示用戶得到授權(與401錯誤相對),但是訪問是被禁止的。
- 404 NOT FOUND - [*]:用戶發出的請求針對的是不存在的記錄,伺服器沒有進行操作,該操作是冪等的。
- 406 Not Acceptable - [GET]:用戶請求的格式不可得(比如用戶請求JSON格式,但是只有XML格式)。
- 410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再得到的。
- 422 Unprocesable entity - [POST/PUT/PATCH] 當創建一個對象時,發生一個驗證錯誤。
- 500 INTERNAL SERVER ERROR - [*]:伺服器發生錯誤,用戶將無法判斷發出的請求是否成功。
返回處理
- GET /collection:返回資源對象的列表(數組)
- GET /collection/resource:返回單個資源對象
- POST /collection:返回新生成的資源對象
- PUT /collection/resource:返回完整的資源對象
- PATCH /collection/resource:返回完整的資源對象
- DELETE /collection/resource:返回一個空文檔
超媒體(Hypermedia API)
github(api.github.com)
訪問第一個
Django開發REST介面
一個簡單的REST介面案例
# 路由 urlpatterns = [ url(r'^games/$', views.GamesAPIView.as_view()), url(r'^games/(?P<id>\d+)/$', views.GameAPIView.as_view()) ]
視圖函數代碼
class GamesAPIView(View): """ 查詢所有的游戲 """ def get(self, request): games = GameInfo.objects.all() game_list = [] for game in games: game_list.append({ 'id': game.id, 'gtitle': game.gtitle, 'game_date': game.game_date, 'game_download': game.game_download, 'gcommnet': game.gcommnet, 'image': game.image.url if game.image else '' }) # 要命令序列化就需要把safe設置成False return JsonResponse(game_list, safe=False) def post(self, request): """ 新增游戲 :param request: :return: """ body_data = request.body data_str = body_data.decode() game_dict = json.loads(data_str) game = GameInfo.objects.create( gtitle=game_dict['gtitle'], game_date= game_dict['game_date'], ) return JsonResponse({ 'id': game.id, 'gtitle': game.gtitle, 'game_date': game.game_date, 'game_download': game.game_download, 'gcommnet': game.gcommnet, 'image': game.image.url if game.image else '' }, status=201) class GameAPIView(View): def get(self, request, id): """ 獲取單個游戲的信息 :param request: :param pk: :return: """ try: game = GameInfo.objects.get(id=id) except GameInfo.DoesNotExist: return HttpResponse(status=404) print(game) return JsonResponse({ 'id': game.id, 'gtitle': game.gtitle, 'game_date': game.game_date, 'game_download': game.game_download, 'gcommnet': game.gcommnet, 'image': game.image.url if game.image else '' }) def put(self, request, id): """ 修改游戲信息 :param request: :param pk: :return: """ try: game = GameInfo.objects.get(id=id) except GameInfo.DoesNotExist: return HttpResponse(status=404) body_data = request.body data_str = body_data.decode() game_dict = json.loads(data_str) game.gtitle = game_dict['gtitle'] game.game_date = game_dict['game_date'] game.save() return JsonResponse({ 'id': game.id, 'gtitle': game.gtitle, 'game_date': game.game_date, 'game_download': game.game_download, 'gcommnet': game.gcommnet, 'image': game.image.url if game.image else '' }) def delete(self, request, pk): """ 刪除游戲 :param request: :param pk: :return: """ try: game = GameInfo.objects.get(id=id) except GameInfo.DoesNotExist: return HttpResponse(status=404) game.delete() return HttpResponse(status=204)
查詢所有數據
增加數據(post提交後面要加/)
獲取單個數據
修改數據
刪除數據
REST介面的核心
1.將數據轉換成模型類的對象(將前端的數據,反序列化為模型類對象,保存到資料庫中)
2.將模型類的對象轉換為響應的數據
3.操作資料庫(將資料庫數據序列化為前端需要的格式)
序列化:
把將一種對象的狀態信息裝換成可以存儲或者可以傳輸形式的過程,比如將模型類轉換成JSON數據,整個過程將序列化(序列化和反序列化執行的過程相似的,也就是可以封裝代碼)