django框架之drf:2、restful规范,序列、反序列化,drf安装及使用(django原生接口及drf接口编写)
Django之drf
一、restful规范
1、概念
REST全称是Representational State Transfer,中文意思是表述:表征性状态转移,它首次出现在2000年Roy Fielding的博士论文中。
RESTful是一种定义Web API接口的设计风格,尤其适用于前后端分离的应用模式中
2、REST的十个规范
数据的安全保障
- 通常使用https(http+ssl/tsl)协议
- url链接一般采用https协议进行传输
- 采用https协议,可以提高数据交互过程中的安全性
接口中带api标识
路径中带版本信息
数据即是资源,均使用名词,避免动词(核心)
-
接口一般都是完成前后台数据的交互,交互数据称之为资源
-
特殊的接口可以出现动词,因为这些接口没有明确的资源或是动词就是接口的核心含义
资源操作由请求方式决定(method)
- 操作资源一般都会涉及到增删改查,我们提供请求方式来标识增删改查动作
- get请求:获取所有书
- get请求:获取主键为1的书
- post请求:新增一本书
- put请求:修改主键为1的书
- delete请求:删除主键为1的书
请求地址中带过滤条件
响应中状态码:两套
- web服务自带状态码
- 1xx:请求正在处理
- 2xx:成功
- 3xx:重定向
- 4xx:客户端错误
- 5xx:服务端错误
- 公司内部规定的状态码,放在响应体中
- 一般使用1000往后的状态码
返回的数据中带错误信息
- {
code:0
msg: "ok/用户名错误"
}
返回的结果遵循以下规范
- GET 获取所有数据:返回资源对象的列表(数组)
- GET 单个对象:返回单个资源对象
- POST 新增对象:返回新生成的资源对象
- PUT 修改对象:返回完整的资源对象
- DELETE 删除:返回一个空文档
响应数据中带链接
- 即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。
{"link": {
"rel": "collection https://www.example.com/zoos",
"href": "https://api.example.com/zoos",
"title": "List of zoos",
"type": "application/vnd.yourformat+json"
}}
二、序列化、反序列化
api接口开发,最核心最常见的一个过程就是序列化,所谓序列化就是把【数据转换格式】,序列化可以分两个阶段:
序列化
把我们识别的数据转换成指定的格式提供给别人
-字典,列表------》json格式存到文件中了
-例如:我们在django中获取到的数据默认是模型对象,但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人
反序列化
把别人提供的数据转换/还原成我们需要的格式。
-例如:前端js提供过来的json数据,对于python而言就是字符串,我们需要进行反序列化换成模型类对象,这样我们才能把数据保存到数据库中
三、drf介绍及快速使用
1、基于django原生编写5个接口
# 以后所写的接口,基本上都是5个接口及其变形
-查询所有
-查询单个
-新增一个
-修改一个
-删除一个
# 基于books单表为例,写5个接口
-创建book表
-表迁移
-录入假数据:直接录,后台管理录
-写查询所有接口---》遵循restful规范,使用cbv
-新增一个数据
-查询一个
-修改一个:put提交的数据,不能从requets.POST中取
-删除一个
import json
from django.shortcuts import render
# Create your views here.
from django.views import View
from .models import Books
from django.http import JsonResponse
class BookViews(View):
def get(self, request):
book_all_queryset = Books.objects.all()
book_data_list = [{'name': book_queryset.name,
'price': book_queryset.price,
'publish': book_queryset.publish}
for book_queryset in book_all_queryset]
return JsonResponse(book_data_list, safe=False, json_dumps_params={'ensure_ascii': False})
def post(self, request):
new_book_obj = Books.objects.create(name=request.POST.get('name'),
price=request.POST.get('price'),
publish=request.POST.get('publish'))
new_book_dict = {
'name': new_book_obj.name,
'price': new_book_obj.price,
'publish': new_book_obj.publish
}
return JsonResponse(new_book_dict, safe=False, json_dumps_params={'ensure_ascii': False})
class BookViews_1(View):
def get(self, request, pk):
book_queryset = Books.objects.filter(pk=pk).first()
if book_queryset:
book_data_dict = {
'name': book_queryset.name,
'price': book_queryset.price,
'publish': book_queryset.publish
}
return JsonResponse(book_data_dict, safe=False, json_dumps_params={'ensure_ascii': False})
return JsonResponse({'msg': '查询失败!无指定编号!'})
def put(self, request, pk):
target_book_queryset = Books.objects.filter(pk=pk).first()
if target_book_queryset:
book_data_dict = json.loads(request.body)
target_book_queryset.name = book_data_dict.get('name')
target_book_queryset.price = book_data_dict.get('price')
target_book_queryset.publish = book_data_dict.get('publish')
target_book_queryset.save()
book_data_dict = {
'name': target_book_queryset.name,
'price': target_book_queryset.price,
'publish': target_book_queryset.publish
}
return JsonResponse(book_data_dict, safe=False, json_dumps_params={'ensure_ascii': False})
return JsonResponse({'msg': '修改失败!无指定编号!'})
def delete(self, request, pk):
target_book_queryset = Books.objects.filter(pk=pk)
if target_book_queryset:
target_book_queryset.delete()
return JsonResponse({})
return JsonResponse({'msg':'删除失败!无指定编号!'})
import json
from django.shortcuts import render
# Create your views here.
from django.views import View
from .models import Books
from django.http import JsonResponse
class BookViews(View):
def get(self, request):
book_all_queryset = Books.objects.all()
book_data_list = [{'pk': book_queryset.pk,
'name': book_queryset.name,
'price': book_queryset.price,
'publish': book_queryset.publish}
for book_queryset in book_all_queryset]
return JsonResponse(book_data_list, safe=False, json_dumps_params={'ensure_ascii': False})
def post(self, request):
new_book_obj = Books.objects.create(name=request.POST.get('name'),
price=request.POST.get('price'),
publish=request.POST.get('publish'))
new_book_dict = {
'name': new_book_obj.name,
'price': new_book_obj.price,
'publish': new_book_obj.publish
}
return JsonResponse(new_book_dict, safe=False, json_dumps_params={'ensure_ascii': False})
class BookViews_1(View):
def get(self, request, pk):
book_queryset = Books.objects.filter(pk=pk).first()
if book_queryset:
book_data_dict = {
'name': book_queryset.name,
'price': book_queryset.price,
'publish': book_queryset.publish
}
return JsonResponse(book_data_dict, safe=False, json_dumps_params={'ensure_ascii': False})
return JsonResponse({'msg': '查询失败!无指定编号!'})
def put(self, request, pk):
target_book_queryset = Books.objects.filter(pk=pk).first()
if target_book_queryset:
book_data_dict = json.loads(request.body)
setattr(target_book_queryset, 'name', book_data_dict.get('name'))
setattr(target_book_queryset, 'price', book_data_dict.get('price'))
setattr(target_book_queryset, 'publish', book_data_dict.get('publish'))
# target_book_queryset.name = book_data_dict.get('name')
# target_book_queryset.price = book_data_dict.get('price')
# target_book_queryset.publish = book_data_dict.get('publish')
target_book_queryset.save()
book_data_dict = {
'name': target_book_queryset.name,
'price': target_book_queryset.price,
'publish': target_book_queryset.publish
}
return JsonResponse(book_data_dict, safe=False, json_dumps_params={'ensure_ascii': False})
return JsonResponse({'msg': '修改失败!无指定编号!'})
def delete(self, request, pk):
target_book_queryset = Books.objects.filter(pk=pk)
if target_book_queryset:
target_book_queryset.delete()
return JsonResponse({})
return JsonResponse({'msg': '删除失败!无指定编号!'})
2、drf的使用
drf全称:djangorestframework,能够帮助我们快速实现符合restful规范的接口
版本及安装
-
版本说明:
- django当前最新版本4.x
- drf最新支持到django3.x,最新不支持2.x
-
安装:
- 我们使用的django版本为2.x,在安装drf后会自动将django升级到最新版本,如果dango版本是3.x就不会出现自动更新的情况,只需在安装drf重新装会2.x版本即可
- pip3 install djangorestframework -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com/simple/
3、drf编写5个接口
# 使用drf编写5个接口(听个响)
# views中
from .serializer import BookSerializer
from rest_framework.viewsets import ModelViewSet
class BookView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
# serializer
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
# urls中
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('books', views.BookView, 'books')
urlpatterns = [
path('admin/', admin.site.urls),
]
# 两个列表相加
urlpatterns += router.urls
四、CBV源码刨析
# 1 路由中写的:path('api/v1/books/', views.BookView.as_view()),第二个参数无论是fbv还是cbv放的都是函数内存地址
-当请求来了,匹配成功会执行,views.BookView.as_view()(request)
-views.BookView.as_view()执行结果是View的类方法as_view返回的结果是内层函数view,是个函数内层地址
-本身请求来了,匹配成功,会执行view(request)
def view(request, *args, **kwargs):
return self.dispatch(request, *args, **kwargs)
-self.dispatch View类的方法
def dispatch(self, request, *args, **kwargs):
# request.method请求方式转成小写,必须在列表中才能往下走
if request.method.lower() in self.http_method_names:
# 反射,去self【视图类的对象:BookView】,去通过get字符串,反射出属性或方法
# BookView的get方法
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
# BookView的get方法,加括号,传入request
return handler(request, *args, **kwargs)