本文使用DRF框架來搭建接口後端框架,接口設計遵循restful定義
爲什麼要使用DRF框架,請參照轉載文章https://www.jianshu.com/p/ae36184e9925
前後端分離
如前後端用django+templates一套體系,templates模版裏有很多隻有django自由的屬性,如block、extends等,後端用的如頁面渲染render(request,'login.html',{'dabing':123123})
,用此方法渲染必須帶一個頁面及字典或其他格式,這樣會導致後端與前端之間的規則要求很高,耦合度增加。如果哪天前端換了vue框架或者新開發了APP端,此時後端只能新開發一套接口才能滿足需求。
django實現restful api的方式
MTV–model view(業務) – 基於函數實現、基於類實現
讀數據:前端發出請求-》業務層-》從數據庫讀取數據(queryset表格)-》序列化 數據庫-》json
寫數據:json-》數據庫
基於函數
- 讀數據
從數據庫讀取數據格式是queryset對象,如果想讓它成爲字典格式需models.Project.objects.values().
多加個values,並轉換成列表LIST格式,最後在用JsonResponse轉換成json格式傳給前端,以下是基於函數實現(手寫)的restful api的代碼
@require_GET
def show(request):
"""
根據項目名稱檢索項目信息
:param request:
:return:
# 返回數據格式:
# 無數據:{"status_code":200,"cata":{"count":0,"Posts":null}}
# 有數據:{"status_code":200,"data":{"count":1,"posts":
# [{"name":"Shop","principal":"大餅", "environment":{"測試環境":"http://dabing.com"}}]}}
"""
name = request.GET.get('name')
if name:
# 1,queryset類型的讀取方式與字典類似,但並非字典,它內部的值都是OBJECT對象。那麼JSON是無法序列化對象的。
# 2,利用values()和values_list()方法,將queryset轉換成字典和列表形式的存儲方式。PS:這樣還不行,還有一步要做。
# 3,再將轉換完的queryset轉換成list列表。 注意:上面的轉換不是轉換成字典或列表,而是字典和列表的數據存儲形式。
# 4,這樣,通過JsonResponse就可以序列化了,重要一點:必須加入safe=False 參數。(因爲咱們序列化的是一個列表)
items = models.Project.objects.values().filter(name__icontains=f'{name.strip()}')
else:
items = models.Project.objects.values().all()
items = list(items)
data = {
'status_code': 200, 'data': {
'Count': len(items), 'Posts': items}}
return JsonResponse(data, safe=False)
- 寫數據
將前端接收的json轉成python對象,通過save入庫
@require_POST
def add(request):
"""
數據格式:{"data":{"name":"ECShop","principal":"dabing", "environment":{"測試環境":"http://dabing.com"}}}
:param request:
:return:
"""
try:
jsondata = json.loads(request.body)
project = models.Project()
project.name = jsonpath.jsonpath(jsondata, '$..name')[0]
project.environment = jsonpath.jsonpath(jsondata, '$..environment')[0]
project.principal = jsonpath.jsonpath(jsondata, '$..principal')[0]
if project.name and project.environment and project.principal:
project.save()
message = Message.Success
else:
message = Message.ArgumentInvalid
except JSONDecodeError:
message = Message.JsonDataError
except IntegrityError:
message = Message.DataDuplicate
except DataError:
message = Message.DataError
return HttpResponse(message)
基於類實現(djangorestframework)
- 繼承ApiView實現(默認方式)
重寫它的get、post等方法,此處的def get(self, request)
裏的request,與上圖如def add(request):
不是一個request,此處是APIView封裝後的request。
寫一個view類,如ProjectAPIView(APIView)
from rest_framework.views import APIView
from api.views3.serializers import ProjectSerializers
from rest_framework.response import Response
from api.models import Project
class ProjectAPIView(APIView):
def get(self, request):
projects = Project.objects.all()
p = ProjectSerializers(projects, many=True)
return Response(p.data)
def post(self, request):
p = ProjectSerializers(data=request.data)
if p.is_valid():
p.save()
return Response(p.data)
else:
return Response(p.errors)
def delete(self, request, pk):
# pk = request.query_params('pk')
Project.objects.get(id=pk).delete()
return Response()
寫一個序列化類,在該類中指定model和序列化的字段如ProjectSerializer(serializers.ModelSerializer):
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = models.Project
fields = '__all__'
2. 繼承ModelViewSet實現 之後都用這個框架來擴展
寫一個view類,例如,ProjectViewSetProject(viewsets.ModelViewSet)
繼承ModelViewSet,會幫你實現create()
, retrieve()
, update()
等操作
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
"""
pass
from django.shortcuts import render
from rest_framework import viewsets
from api import serializers
from api import models
# Create your views here.
class ProjectViewSet(viewsets.ModelViewSet):
#指定數據集,是在這個數據集範圍內做序列化
queryset = models.Project.objects.all()
#指定所需序列化的類
serializer_class = serializers.ProjectSerializers
創建序列化類
from rest_framework import serializers
from api import models
class ProjectSerializers(serializers.ModelSerializer):
class Meta:
# 指定那個model裏的表做序列化
model = models.Project
# 所要序列化的字段,'__all__'是全部字段
# fields = ('id','name')
fields = '__all__'
配置路由
from django.urls import path,include
from rest_framework import routers
from api import views
# 創建路由
router = routers.DefaultRouter()
# 註冊路由,只要後綴是project,會找視圖ProjectViewSet裏的方法
router.register('project', viewset=views.ProjectViewSet)
urlpatterns = [
# 只要8000端口後帶api/會掃router裏所註冊的路由地址
path('api/', include(router.urls)),
]
setting增加rest_framework
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'api',
'rest_framework',
]
以上把繼承ModelViewSet的框架已經搭建好,已經可以實現基本的增刪改查操作,通過請求資源類型來決定接口的操作,URL沒變,變的只是數據,遵循restful api規範,非常簡單!
調用方式:
查詢:http://ip:8000/project 請求方式:get 返回:json 返回格式默認是列表格式,因爲可能會有多條數據
http://ip:8000/project/1 請求方式:get 返回:json 查詢某一條記錄,查詢、修改、刪除都類似
後續會增加過濾、重寫create(),
retrieve(),
update()`、定製錯誤格式、定製返回報文等。