本文使用DRF框架来搭建接口后端框架,接口设计遵循restful定义
为什么要使用DRF框架,请参照转载文章https://www.jianshu.com/p/ae36184e9925
如前后端用django+templates一套体系,templates模版里有很多只有django自由的属性,如block、extends等,后端用的如页面渲染render(request,'login.html',{'dabing':123123})
,用此方法渲染必须带一个页面及字典或其他格式,这样会导致后端与前端之间的规则要求很高,耦合度增加。如果哪天前端换了vue框架或者新开发了APP端,此时后端只能新开发一套接口才能满足需求。
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)
def get(self, request)
里的request,与上图如def add(request):
不是一个request,此处是APIView封装后的request。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()`、定制错误格式、定制返回报文等。