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})

image

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})

image

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/

image

使用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)