restful规范、序列化与反序列化、基于django原生编写五个接口、drf的介绍与使用、cbv源码分析
restful规范
restful全称是Representational State Transfer,中文意思是表述:表征性状态转移,它首次出现在2000年Roy Fielding的博士论文中。
restful是一种定义web API接口的设计风格,尤其适用于前后端分离的应用模式中
restfulde 10个规范
1.数据的安全保障:URL链接一般采用https协议进行传输
使用https传输协议是为了保证数据的安全
https----->>http+ssl/tsl
2.接口中带有api接口标识
-https://api.zx.com/books
-https://www.zx.com/api/books
3.多数据版本共存,一个接口可能有多个版本
-https://api.zx.com/v1/login
-https://www.zx.com/api/v2/login
4.数据即资源,均使用名词(尽量不要出现动词)
接口要完成前后台数据的交互,交互的数据我们称为资源
5.资源操作由请求方式决定
我们提供请求方式来标识增删改查动作
https://api.baidu.com/books -get请求:获取所有书
https://api.baidu.com/books/1 -get请求:获取主键为1的书
https://api.baidu.com/books -post请求:新增一本书
https://api.baidu.com/books/1 -put请求:修改主键为1的书
https://api.baidu.com/books/1 -delete请求:删除主键为1 的书
增-->post 删-->delete 改-->put 查-->get
6.URL中带过滤参数
https://api.baidu.com/books?name=张昕呀&price=999
7.响应状态码(有两套)
1xx-->响应中 2xx-->成功 3xx-->重定向 4xx-->客户端错误 5xx-->服务端错误 200---->处理成功
301---->重定向(永久移动)
302---->重定向(临时移动)
400---->客户端请求有语法错误
403---->Forbidden 服务器拒绝提供服务
404---->Not Found 请求资源不存在
500---->服务器发生不可预期的错误
除了这些公司内部都会规定状态码,在响应体中写状态码
{code:100}
8.返回错误信息(在响应体中带有错误的信息)
{code:404,msg:资源不存在}
9.返回的结果应该符合一下规范
GET 获取所有的数据:返回资源对象是列表套数组 [{name:西游记,price:99},{name:红楼梦,price:999}]
GET 获取单个数据:返回单个资源对象 {name:西游记,price:99}
POST 新增对象:返回新生成的资源对象 {name:西游记,price:199}
PUT 修改对象:返回完整的资源对象 {name:西游记,price:299}
DELETE 删除:返回一个空文档
10.响应数据中带链接的
序列化与反序列化
api接口开发,最核心最常见的一个过程就是序列化,所谓序列化就是把数据转换格式,序列化可以分两个阶段:
序列化:把我们识别的数据转换为指定的格式提供给别人
例如:我们在django中获取到的数据默认是模型对象(queryset),但是模型对象数据无法直接提供给前端或者别的平台使用,所以我们需要吧数据进行序列化,变成字符串或者json数据
反序列化:把别人提供的数据转换为我们需要的数据格式
基于django原生编写5个接口
基于books单表为例,写5个接口
1.创建book表:
from django.db import models
# Create your models here.
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32)
publish = models.CharField(max_length=32)
2.表迁移
3.录入假数据:直接录,后台管理录
4.写查询所有接口---》遵循restful规范,使用cbv
class BookView(View):
# 查询所有
def get(self, request):
# 查询所有的图书,查出的数据是queryset类型的,不能直接传给前端,转成json格式才能行
books = Book.objects.all()
# 把queryset转换为列表,然后再使用JsonResponse
book_list = []
for book in books:
book_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
# return HttpResponse(json.dumps(book_list,ensure_ascii=False))
return JsonResponse(book_list,safe=False,json_dumps_params={'ensure_ascii':False}) # JsonResponse里面只能存放列表或者字典
5.新增一个数据
# 新增数据(只能使用urlencoded或form-data编码,使用json形式编码不行,因为json格式编码提交的数据,不能从request.POST中取)
def post(self,request):
# 取出前端传入的数据
name = request.POST.get('name')
price = request.POST.get('price')
publish = request.POST.get('publish')
# 存放到数据库中
book = Book.objects.create(name=name,price=price,publish=publish)
# 返回到新增字典中
return JsonResponse({'name': book.name, 'price': book.price, 'publish': book.publish})
6.查询一个数据
class BookDetailView(View):
# 获取单条数据
def get(self,request,pk):
book = Book.objects.filter(pk=pk).first()
# 将模型对象转换为字典,然后用JsonResponse返回
return JsonResponse({'id':book.id,'name':book.name,'price':book.price,'publish':book.publish})
7.修改一个:put提交的数据,不能从requets.POST中取
def put(self,request,pk): # request.POST只能取post提交的urlencoded或form-data编码数据,put提交的取不到
# 先查到要改的数据
book = Book.objects.filter(pk=pk).first()
# 前端使用json格式提交
print(request.body)
book_dict = json.loads(request.body)
book.name = book_dict.get('name')
book.price = book_dict.get('price')
book.publish = book_dict.get('publish')
book.save()
# 将数据模型对象转换为字典,然后返回
return JsonResponse({'id':book.id,'name':book.name,'price':book.price,'publish':book.publish})
8.删除一个数据
# 删除单行数据
def delete(self,request,pk):
Book.objects.filter(pk=pk).delete()
return JsonResponse(data={})
drf的介绍与使用
djangorestframework: drf 帮助我们快速的实现符合restful规范的接口
#安装drf:
在pycharm终端敲如下命令安装djangorestframework:
pip3 install djangorestframework -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com/simple/
# 问题:安装好djangorestframework后,由于你是django2.x 它发现它不支持,它会自动写在dajgno,安装最新的django 4.x,为了我们更好的使用,手动安装2.x
安装命令:
pip3.8 install django===2.2.2 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com/simple/
使用drf编写5个接口(先了解一下)
serializer.py
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
views.py
# 使用drf编写五个接口
from .serializer import BookSerializer
from rest_framework.viewsets import ModelViewSet
class BookView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
url.py
from django.contrib import admin
from django.urls import path
from day01 import views
# 使用drf写5个接口
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('books',views.BookView,'books')
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/books', views.BookView.as_view())
]
# 两个列表相加
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)