Django REST framework框架深度學習(一)

本文使用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-》數據庫

基於函數

  1. 讀數據

從數據庫讀取數據格式是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)
  1. 寫數據

將前端接收的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)

  1. 繼承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()`、定製錯誤格式、定製返回報文等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章