Django:DjangoRestFramework drf 開發1
技術標籤:Python Djangodjangopythonrestfuljson資料庫
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 介面;
-
可擴充套件性,外掛豐富。
1. Django RESTFul 協議
1. 伺服器端程式碼
1. 定義類檢視
class ***View(View):
def get(self):
def post(self):
2. 檢視函式處理步驟
- 接收、驗證、處理、響應
3. 配置處理路由規則
4. get或post隨便起,但會影響程式碼可讀性和規範性
2. 規範
1. 規則:
- 規定伺服器端程式設計師需要按照哪些標準定義檢視、路由規則
2. 作用:
- 增強程式碼可讀性,降低前後端程式設計師的溝通成本,提高效率
2. RESTFul協議設計方法
1. 域名
應該儘量將API部署在專用域名之下
https://api.example.com
如果確定API很簡單,不會有進一步擴充套件,可以考慮放在主域名下。
https://example.org/api/
2. 版本(Versioning)
應該將API的版本號放入URL
http://www.example.com/app/1.0/foo
http://www.example.com/app/1.1/foo
http://www.example.com/app/2.0/foo
3. 路徑(Endpoint) 路由規則
路由中的正則表示式必須是名詞,建議使用複數,如/books/,/heros/
4. HTTP動詞
請求方式 | 資料庫資料處理 |
---|---|
GET | 查詢 |
POST | 增加 |
PUT | 修改(PUT需要給所有值賦值,PATCH可以修改部分屬性) |
DELETE | 刪除 |
以下請求方式用的相對較少:
請求方式 | 資料庫資料處理 |
---|---|
PATCH | 在伺服器更新(更新)資源(客戶端提供改變的屬性) |
HEAD | 獲取資源的元資料 |
OPTIONS | 獲取資訊,關於資源的哪些屬性是客戶端可以改變的 |
5. 以查詢引數提供過濾條件、分頁資訊、排序規則
- https://www.baidu.com/python/?a=3&b=5 -->問號後是查詢引數
6. 狀態碼
狀態碼 | 含義 |
---|---|
200 | 查詢成功 |
201 | 新建或修改成功 |
204 | 刪除成功 |
3xx | 重定向 |
4xx | 客戶端請求有錯誤 |
5xx | 伺服器有錯 |
7. 返回值
處理方式 | 響應值 |
---|---|
查詢 | {json}或[列表,內部有字典] |
增加 | 新建的物件{} |
修改 | 修改後的物件{} |
刪除 | 無 |
8. 所有資料以JSON格式返回
比如 錯誤資訊:
{
error: 'Invalid API key'
}
3. 使用Django開發REST介面
以圖書的查詢、增加、修改、刪除為例
處理 | 請求路徑 | 請求方式 | 響應值 | 狀態碼 |
---|---|---|---|---|
查詢(所有) | /books/ | GET | [{},{},…] | 200 |
增加 | /books/ | POST | 新增的資料{} | 201 |
查詢(指定主鍵) | /books/(?P\d+)/ | GET | {} | 200 |
修改 | /books/(?P\d+)/ | PUT | 修改後的物件{} | 201 |
刪除 | /books/(?P\d+)/ | DELETE | 無 | 204 |
開發需要兩個類檢視,一個不包含pk,一個包含pk。
- settings.py 註冊子應用
'book.apps.BokConfig',
- book/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^books/$', views.BooksView.as_view()),
url(r'^books/(?P<pk>\d+)/', views.BookView.as_view()),
]
- views.py 檢視函式的結構
from django.views import View
class BooksView(View):
def get(self, request):
'''查詢所有'''
pass
def post(self, request);
'''新增'''
pass
class BookView(View):
def get(self, request, pk)
'''根據主鍵查詢一個圖書物件'''
pass
def put(self, request, pk)
'''修改指定主鍵的圖書物件'''
pass
def delete(self, request, pk)
'''刪除指定主鍵的圖書物件'''
pass
- views.py 具體實現:
from django.views import View
from .models import Books
from django.http import JsonResponse
import json
class BooksView(View):
""" 圖書類檢視 """
def get(self, request):
""" 獲取所有圖書資訊 """
# 接收
# 驗證
# 處理
# 1. 查詢所有圖書物件
book_obj = Books.objects.all()
# 2. 將圖書物件轉成dict型別
book_info = []
for book in book_obj:
book_info.append({
'id': book.id,
'book_name': book.book_name,
'author': book.author,
'type': book.type,
'published_date': book.published_date,
'date_joined': book.date_joined
})
# 響應
return JsonResponse(book_info, safe=False) # 狀態碼預設是200,此處無需返回狀態碼
def post(self, request):
""" 新增圖書 """
# 接收
params = json.loads(request.body.decode())
book_name = params.get('book_name')
author = params.get('author')
type = params.get('type')
published_date = params.get('published_date')
date_joined = params.get('date_joined')
# 驗證
book_obj = Books.objects.filter(book_name=book_name).first()
if book_obj:
return JsonResponse({'error': 'this book is exist!'})
# 處理
# 1. 建立圖書
book = Books.objects.create(book_name=book_name, author=author, type=type, published_date=published_date,date_joined=date_joined)
# 2. 將新建立的圖書物件轉成dict
book_dict = {
'id': book.id,
'book_name': book.book_name,
'author': book.author,
'type': book.type,
'published_date': book.published_date,
'date_joined': book.date_joined
}
# 響應
return JsonResponse(book_dict, status=201) # 新增成功返回狀態碼 201
class BookView(View):
""" 圖書類檢視(含pk) """
def get(self, request, pk):
""" 獲取一個圖書資訊 """
try:
book = Books.objects.get(pk=pk)
except:
return JsonResponse({"error": "資料不存在"})
book_dict = {
'id': book.id,
'book_name': book.book_name,
'author': book.author,
'type': book.type,
'published_date': book.published_date,
'date_joined': book.date_joined
}
return JsonResponse(book_dict)
def put(self, request, pk):
""" 修改一個圖書資訊 """
# 接收
params = json.loads(request.body.decode())
book_name = params.get('book_name')
author = params.get('author')
type = params.get('type')
published_date = params.get('published_date')
date_joined = params.get('date_joined')
# 驗證
try:
book = Books.objects.get(pk=pk)
except:
return JsonResponse({"error": "資料不存在"})
# 更新資料
# 這個方法不行,報【AttributeError: 'Heros' object has no attribute 'update'】錯。暫時還不知道為啥,就用了未註釋的這種
# book.update(book_name=book_name, author=author, type=type, published_date=published_date,date_joined=date_joined)
book.book_name = book_name
book.author = author
book.type = type
book.published_date = published_date
book.date_joined = date_joined
book.save()
# 將物件轉換成字典
book_dict = {
'id': book.id,
'book_name': book.book_name,
'author': book.author,
'type': book.type,
'published_date': book.published_date,
'date_joined': book.date_joined
}
# 響應
return JsonResponse(book_dict, status=201) # 修改成功返回狀態碼 201
# 處理
def delete(self, request, pk):
""" 刪除一個圖書 """
# 接收、驗證、處理
try:
Books.objects.get(pk=pk).delete()
except:
return JsonResponse({"error": "資料不存在"})
# 響應
return JsonResponse(data={}, status=204) # data= 可寫可不寫
# 以下是patch方法修改模型類的部分資訊,用的不多
def patch(self, request, pk):
""" 使用patch,根據主鍵pk修改圖書部分資訊 """
# 接收資料
params = json.loads(request.body.decode())
# book_name = params.get('book_name')
author = params.get('author')
# type = params.get('type')
# published_date = params.get('published_date')
# date_joined = params.get('date_joined')
# 驗證
try:
book= Books.objects.get(pk=pk)
except:
return JsonResponse({"error": "該圖書不存在"})
# 修改
# book.book_name = book_name
book.author = author # 只改圖書的作者
# book.type = type
# book.published_date = published_date
# book.date_joined = date_joined
book.save()
# 將資料物件轉成字典
book_dict = {
'id': book.id,
'book_name': book.book_name,
'author': book.author,
'type': book.type,
'published_date': book.published_date,
'date_joined': book.date_joined
}
return JsonResponse(hero_dict, status=201)
如有不足,請多指教!