Django REST framework框架深度学习(一)

时间:2021-1-18 作者:admin

本文使用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 查询某一条记录,查询、修改、删除都类似
Django REST framework框架深度学习(一)
Django REST framework框架深度学习(一)
Django REST framework框架深度学习(一)

后续会增加过滤、重写create(),retrieve(),update()`、定制错误格式、定制返回报文等。

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。