1. 程式人生 > 其它 >Django:DjangoRestFramework drf 開發1

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+)/DELETE204

開發需要兩個類檢視,一個不包含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)

如有不足,請多指教!