drf 框架基础

落爺英雄遲暮 提交于 2019-12-01 10:25:43

drf 基础
   1.接口:什么 是接口 restful接口规范
    2、CBV生命周期源码 - 基于restful规范下的CBV接口
    3、请求组件、解析组件、响应组件
    4、序列化组件(灵魂)
    5、三大认证(重中之重):认证、权限(权限六表)、频率
    6、其他组件:过滤、筛选、排序、分页、路由

 

接口:

'''
接口:联系两个物质的媒介,完成信息交互
web程序中:联系前台页面与后台数据库的媒介
web接口组成:
    url:长的像返回数据的url链接
    请求参数:前台按照指定的key提供数据给后台
    响应数据:后台与数据库交互后将数据反馈给前台
'''

restful接口规范

  

接口规范:就是为了采用不同的后台语言,也能使用同样的接口获取到同样的数据

如何写接口:接口规范是 规范化书写接口的,写接口要写 url、响应数据

​        注:如果将请求参数也纳入考量
 

 

范围,那就是在写 接口文档

两大部分:  url   1,用api关键字标识接口url    api.baidu.com | www.baidu.com/api   2,接口数据安全性决定优先选择https协议   3,如果一个接口有多个版本存在,需要在url中标识体现     api.baidu.com/v1/... | api.baidu.com/v2/...   4,接口操作的数据源称之为 资源,在url中一般采用资源复数形式,一个接口可以概括对该资源的多种操作方式     api.baidu.com/books | api.baidu.com/books/(pk)    
    5) 请求方式有多种,用一个url处理如何保证不混乱 - 通过请求方式标识操作资源的方式
       /books  get   获取所有
        下面的四个完全兼容get请求
       /books  post  增加一个(多个)
       /books/(pk) delete  删除一个
        /books/(pk) put   整体更新一个
        /books/(pk) patch  局部更新一个

    6) 资源往往涉及数据的各种操作方式 - 筛选、排序、限制
       api.baidu.com/books/?search=西&ordering=-price&limit=3
  响应方式:    1) http请求的响应会有响应状态码,接口用来返回操作的资源数据,可以拥有 操作数据结果的 状态码       status  0(操作资源成功)  1(操作资源失败)  2(操作资源成功,但没匹配结果)       注:资源状态码不像http状态码,一般都是后台与前台或是客户约定的
      数据状态码: 例如:status  0(操作资源成功) 
      数据提示:   例如: msg:登录失败
      资源本身:要返回的资源 
    2) 资源的状态码文字提示       status  ok '账号有误'  '密码有误'  '用户锁定'     3) 资源本身       results       注:删除资源成功不做任何数据返回(返回空字符串)     4) 不能直接返回的资源(子资源、图片、视频等资源),返回该资源的url链接        总结:接口由两部分组成:url(其实就是一个接口),响应数据.请求数据       url:        1,首相遵循restful接口规范协议        2,在url前要加上https:决定接口数据的安全性(头)        3,用api关键字标识接口url        4,接口操作资源(数据),通常以复数显示,里面包括对该资源的多种操作方式(get,post,delete,put,patch)       响应数据:        1,status,资源状态码        2,资源的状态码文本提示:        3,资源本身:即要返回给前端的数据          ps:不能直接返回的资源有图片,视频,子资源          通过请求方式(get|post|update|patch|delete)来操作资源,还有在url中可以对数据进行限制 ,排序等等            通过发送请求,可以拿到后台按照规范的响应数据,数据是一个超大的{}              资源状态码              资源的状态码文本提示              result资源本身             案列{                'status':0,                'msg':'ok',                'result':[{                   'title':*,                   'price':*,                   'img':https://*                   }]

  

基于restful规范的原生Django接口

主路由:url.py


from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    
    #路由分发
    url(r'^api/',include('api.urls'))]

api组件的子路由:api/url.py

    from django.conf.urls import url

    from . import views
    urlpatterns = [
        url(r'^books/', views.Book.as_view()),
        url(r'^books/(?P<pk>.*)/$', views.Book.as_view()),
            ]

模型层:model.py

 from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=64)
    price = models.DecimalField(max_digits=5, decimal_places=2)

    class Meta:
        db_table = 'old_boy_book'
        verbose_name = '书籍'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '《%s》' % self.title        
后台层:admin.py
from django.contrib import admin

from . import models

admin.site.register(models.Book)
数据库迁移
>: python manage.py makemigrations
>: python manage.py migrrate

>: python manage.py createsuperuser

视图层:views.py

 

from django.http import JsonResponse
# Create your views here.
from django.views import View
from . import models
class Book(View):
    def get(self,request,*args,**kwargs):
        # 路由分发,有名分组即关键字传参
        pk = kwargs.get('pk')
        if not pk: # 群查
            # 从数据库中获取数据
            book_list_obj = models.Book.objects.all()
            # 序列化过程
            book_list = []
            for obj in book_list_obj:
                print(obj)
                # 把数据转化为字典格式,解压赋值
                dic = {}
                dic['title'] = obj.title
                dic['price'] = obj.price
                book_list.append(dic)
                #返回 响应数据
            return JsonResponse({
                'status':0,
                'msg':'ok',
                'result':book_list    # 后端处理后的数据
            },json_dumps_params={'ensure_ascii':False})  # 转换为前端识别的json格式

        else:       # 单查
            book_dic = models.Book.objects.filter(pk=pk).values('title','price').first()
            if book_dic:
                return JsonResponse({
                    'status':0,
                    'msg':'ok',
                    'result':book_dic,
                },json_dumps_params={'ensure_ascii':False})
            return JsonResponse({
                'status': 2,
                'msg': '无结果',
                }, json_dumps_params={'ensure_ascii': False})

    # postman 可以完成不同方式的请求:get|post|put....
    # postman 发送数据包的方式有三种:form-data|urlencoding|json
    # 原生django对urlencoding方式数据兼容最好


    def post(self,request,*args,**kwargs):
        print(request.POST)     #<QueryDict: {'title': ['三国演义'], 'price': ['2.99']}>
        print(request.body)
        res = request.POST
        print(res.dict())
        # 前台通过urlencoding方式提交数据
        try:                                            # **request.POST.dict() 打散,request拥有dict方法
            book_obj = models.Book.objects.create(**request.POST.dict())
            if book_obj:
                return JsonResponse({
                    'status':0,
                    'msg':'ok',
                    # 获取前端数据,把真实数据字典赋值
                    'result':{'title': book_obj.title,'price':book_obj.price}
                },json_dumps_params={'ensure_ascii':False})
        except:
            return JsonResponse({
                    'status':1,
                    'msg':'数据有误',
            },json_dumps_params={'ensure_ascii':False})

        return JsonResponse({
            'status':2,
            'msg':'增加失败',
        },json_dumps_params={'ensure_ascii':False})

 

Postman接口工具

  官网下载安装

  get请求,携带参数采用Params

  post等请求,提交数据包可以采用三种方式:form-date、urlencoding、json

  所有请求都可以携带请求头

 

DRF框架

  安装:在pycharm命令行: pip3 install djangorestframework

  drf框架规矩的封装风格

  注册:在settings.py文件中进行注册:

      

INSTALLED_APPS = [    'django.contrib.admin',    'django.contrib.auth',    'django.contrib.contenttypes',    'django.contrib.sessions',    'django.contrib.messages',    'django.contrib.staticfiles',    'api.apps.ApiConfig',   # 在这里进行注册    'rest_framework',]
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.serializers import Serializer
from rest_framework.settings import APISettings
from rest_framework.filters import SearchFilter
from rest_framework.pagination import PageNumberPagination
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.throttling import SimpleRateThrottle

class Test(APIView):
    def get(self, request, *args, **kwargs):
        return Response('drf get ok')

 

drf请求生命周期

  1) 请求走的是APIView的as_view函数

  2) 在APIView的as_view调用父类(django原生)的as_view,还禁用了 csrf 认证

  3) 在父类的as_view中dispatch方法请求走的又是APIView的dispatch
    1,其中有一句:
      view = super().as_view(**initkwargs)
      自定义类继承了APIView,在调用时 会走as_view()方法,但是APIView中没有as_view方法,又因为APIView
      它继承了View类,在View类中存在as_view()方法,所以此时走的就是View类中存在as_view()方法
    2,在View类中存在as_view()方法中
      return self.dispatch(request, *args, **kwargs)
      此时的self就是Test,所以此时调用的就是父类的dispatch方法,
 
  4) 完成任务方法交给视图类的请求函数处理,得到请求的响应结果,返回给前台
    ps:如果继承了 APIView所有的子类,就默认将csrf的中间件给禁用了(即帮你注释了),
      因为他自己有认证,他的认证比这高级,而且还可以自定义
    在混用的时候,csrf对于原生的django还是使用的,只有继承了APIView的子类,才会拥有drf认证
    总结:继承了APIView的视图类,会禁用csrf认证
class APIView(View):    # The following policies may be set at either globally, or per-view.    # 渲染模块renderer_classes    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES    # 解析模块    parser_classes = api_settings.DEFAULT_PARSER_CLASSES    # 认证模块    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES    content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS    metadata_class = api_settings.DEFAULT_METADATA_CLASS    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        # 在这里是对象获取自己的属性
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            # 下面这句话执行出异常就会走drf提供的异常 response = self.handle_exception(exc)
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                # 原生django提供的异常
                handler = self.http_method_not_allowed

            response = handler(request, *args, **kwargs)
        # drf提供的异常
        except Exception as exc:
            #原生的数据
            response = self.handle_exception(exc)
        # 在这里判断是浏览器发来的还是页面发来的(请求方式)再加以包装最终返回数据
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
            

 

 
 
 
 

 

 

 

 

 

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!