首页 > 其他 > 详细

DRF(一)

时间:2019-09-02 21:25:05      阅读:56      评论:0      收藏:0      [点我收藏+]

一.HTTP协议与wsgi协议

http协议
    应用层协议
    请求与响应规范:首行 - 头 - 体
    特点:无状态、无连接、请求永远是客户端到服务器端、ssl
    
wsgi协议
    原生django启动项目 - 启动了server socket - wsgiref - uWSGI(项目上线)
    规定数据的解析方式:
        get数据、post数据(数据数据) => request => 回调的视图函数
        返回响应对象 - HTTPResponse类对象 - 数据、响应状态码

二.接口

url链接:http://api.oldboy.com/login/
请求方式:get | post | put ...
请求参数:username | password
响应结果:result | data

利用Postman连接百度接口:

method: GET
url: https://api.map.baidu.com/place/v2/search
params:
    ak: 6E823f587c95f0148c19993539b99295
    region: 上海
    query: 肯德基
    output: json

原生Djiango实现接口:

models.py

  from django.db import models
  class Book(models.Model):
     name = 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 self.name

class User(models.Model):
    SEX_CHOICES = [
        (0, ),
        (1, ),
        (2, 哇塞)
    ]
    username = models.CharField(max_length=64)
    password = models.CharField(max_length=64)
    sex = models.IntegerField(choices=SEX_CHOICES, default=0)
    # 需要配置media工作目录与路由
    icon = models.ImageField(upload_to=icon, default=/icon/default.png)
    class Meta:
        db_table = old_boy_user
        verbose_name = 用户
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username

 

创建Django项目并设置默认app名为api,完成路由分发:


# 主路由
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应用下的子路由
from django.conf.urls import url
from . import views
urlpatterns = [
    # as_view() 本质拿到 view函数地址,
    # view内部通过dispatch分发请求给具体的(get|post|delete)方法处理请求
    # 处理完后的响应结果会一层层返回
    url(r^books/$, views.BookView.as_view()),
    url(r^books/(?P<pk>.*)/$, views.BookView.as_view()),
]

数据库迁移:

>: python manage.py makemigrations
>: python manage.py migrate
后台管理:

from django.contrib import admin
from . import models
admin.site.register(models.Book)
admin.site.register(models.User)

# 创建超级用户
# >: python manage.py createsuperuser
views.py

from django.views import View
from django.http import JsonResponse
from . import models
class BookView(View):
    def get(self, request, *args, **kwargs):
        pk = kwargs.get(pk)
        if pk:  # 通过是否有主键决定获取单个或是全部资源
            book_dic_list = models.Book.objects.filter(pk=pk).values(name, price)
            if not book_dic_list:
                return JsonResponse({
                    status: 2,
                    msg: pk值有误,
                    results: {}
                })
            return JsonResponse({
                status: 0,
                msg: ok,
                results: book_dic_list[0]
            })

        book_dic_list = models.Book.objects.all().values(name, price)
        if not book_dic_list:
            return JsonResponse({
                status: 2,
                msg: 无数据,
                results: {}
            })
        return JsonResponse({
            status: 0,
            msg: ok,
            results: list(book_dic_list)
        })

开一个media窗口:

##### media工作目录:settings.py

```python
# MEDIA_URL = ‘/media/‘
MEDIA_ROOT = os.path.join(BASE_DIR, media)
```

##### 路由:主urls.py

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

from django.views.static import serve
from django.conf import settings
urlpatterns = [
    url(r^admin/, admin.site.urls),
    url(r^api/, include(api.urls)),
    url(r^media/(?P<path>.*), serve, {document_root: settings.MEDIA_ROOT})
]
```

 

 

三.restful接口十条规范

1)一般都采用安全协议(接口都是操作数据的):https

2)体现接口的关键字:api
    https://api.oldboy.com
    https://www.oldboy.com/api

3)接口操作的数据称之为资源:采用资源名称的复数
    https://api.oldboy.com/books/
    https://api.oldboy.com/users/

4)接口链接中不出现操作资源的动词,通过请求方式来决定操作资源的动作
    https://api.oldboy.com/books/
    get:获取所有 | post:增加一个 
    https://api.oldboy.com/books/(?P<pk>)/
    get:获取一个 | put:整体修改一个(patch:局部修改一个) | delet:删除一个

5)资源数据有多版本时,接口可以做版本控制
    https://api.oldboy.com/books/v1/
    https://api.oldboy.com/v2/books/
    
6)资源响应的限制条件:筛选、排序、限制...
    https://api.oldboy.com/books/?publish=1&ordering=-price&limit=3
    
7)响应状态码
    网络状态码:2xx | 3xx | 4xx | 5xx
    数据状态码(约定的):0 | 1 | 2
    {
        status: 1,
    }
    -- SUCCESS(0, "查询成功")
    -- NODATA(1, "非正确,无数据,显示基本信息")
    -- FEAILED(2, "查询失败")

8)响应结果的信息描述:
    {
        status: 1,
        msg: login failed
    }

9)响应的结果:get所有:所有资源 | get一个:一个资源 | post、put、patch:新增、修改的资源 | delete:不做任何返回
    {
        status: 0,
        msg: ok,
        results: [登录的用户对象序列化结果]
    }
    
10)响应结果中有二次资源(用户头像:图片链接,用户详情:详情接口)
    要表明请求二次资源的接口

注:通过 接口文档 告诉前台传递的必要和选填参数

四.drf框架

安装:

pip3 install djangorestframework
配置:settings.py
# 注册drf app
NSTALLED_APPS = [
    # ...
    rest_framework,
]

特点:

# 具体功能在具体模块下
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.exceptions import APIException
from rest_framework.filters import OrderingFilter
from rest_framework.views import APIView
from rest_framework.pagination import PageNumberPagination
from rest_framework.settings import APISettings

# 自定义drf配置 - 在自己的settings.py
REST_FRAMEWORK = {
    # 自定义修改drf的配置们
}

五.源码分析APIView

        1.django中的CBV:

 url(r^books/, views.Books.as_view()),

           发现Books类调用as_view方法,自身类没有则找父类View, 进入源码发现它返回的是view的函数地址,

请求来了,则根据路由匹配去找视图函数,依然会找到父类View中的view函数,返回的是self.dispatch方法,self指的是Book

对象,自身没有,还是找父类中的dispatch方法;

http_method_names = [get, post, put, patch, delete, head, options, trace]

         首先判断方法名小写在不在django支持的这八种方法里面,如果在,并且Book类中有此方法,以反射获取方法值赋予句柄

handle,否则赋予 http_method_not_allowed方法的返回值给handle,状态码是405, 最后将handle返回;获取正确方法则进入视图

函数,并将响应结果逐层返回.

          2.rest_framework中的CBV:

          Book类继承的是APIView, 而APIView继承的是View, APIView是从rest_framework框架中导进来的,as_view方法返回的

是 csrf_exempt(view),也就是不会经过csrf中间件认证;

          请求来了调用view函数,内部调用(APIView类的)dispatch函数完成请求分发;

       request = self.initialize_request(request, *args, **kwargs)

         dispatch中对request进行了一次封装,在initialize_request函数中返回的的是Request类的一个实例化,看它的__init__方法就

发现把原生django的request对象当做Request类对象的_request属性,所以封装后的request._request仍然是wsgi的request对象,

而request变成了rest_framework的request对象

        dispatch还在self.initial中完成了三大认证: 认证/权限/频率

        再将请求方式映射到视图函数的同名的方法中,得到响应后渲染,并将响应结果逐层返回

 

六.响应渲染模块:json和浏览器接口页面

# 入口:APIView类的dispatch函数
self.response = self.finalize_response(request, response, *args, **kwargs)
->
neg = self.perform_content_negotiation(request, force=True)
->
renderers = self.get_renderers()
->
self.renderer_classes
->
APISetting:DEFAULT_RENDERER_CLASSES
   局部配置(在视图函数中):
from rest_framework.views import APIView
from rest_framework.response import Response

from rest_framework.renderers import JSONRenderer
from rest_framework.renderers import BrowsableAPIRenderer
class UserAPIView(APIView):
    # 局部配置:只有该视图类起作用
    renderer_classes = [JSONRenderer]  # 只提供JSON数据渲染
    pass

  

全局配置(在django的settings.py文件中):
# drf配置
REST_FRAMEWORK = {
    # 响应的渲染模块
    DEFAULT_RENDERER_CLASSES: [
        rest_framework.renderers.JSONRenderer,
        rest_framework.renderers.BrowsableAPIRenderer,
    ],
}

七.请求数据解析模块:json、form-data、urlencoding

 

# 入口:APIView类的dispatch函数
request = self.initialize_request(request, *args, **kwargs)
->
parsers=self.get_parsers()
->
self.parser_classes
->
APISetting:DEFAULT_PARSER_CLASSES

局部配置:

from rest_framework.views import APIView
from rest_framework.response import Response

from rest_framework.parsers import JSONParser
from rest_framework.parsers import FormParser
from rest_framework.parsers import MultiPartParser
class UserAPIView(APIView):
    # 局部配置:只有该视图类起作用
    parser_classes = [JSONParser]  # 只提供JSON解析
    pass

全局配置:

# drf配置
REST_FRAMEWORK = {
    # 响应的渲染模块
    DEFAULT_RENDERER_CLASSES: [
        rest_framework.renderers.JSONRenderer,
        rest_framework.renderers.BrowsableAPIRenderer,
    ],
    # 请求数据解析模块
    DEFAULT_PARSER_CLASSES: [
        rest_framework.parsers.JSONParser,  # ‘application/json‘
        rest_framework.parsers.FormParser,  # ‘application/x-www-form-urlencoded‘
        rest_framework.parsers.MultiPartParser  # multipart/form-data
    ],
}

请求数据解析位置:

 请求的数据包:均解析到 request.data 中
 请求的?文件参数(get请求url拼接参数):均解析到 request.query_params 中

八.响应模块

# 响应可以设置响应数据、响应网络状态码、响应头、响应数据类型等
data = {
    status: 0,
    msg: get ok,
    results: [],
    token: 123.12321.231
}
return Response(
    data=data,
    status=status.HTTP_200_OK,
    headers={Token: 123as.masd21.asd213sd},
    content_type=application/json  # 默认就是application/json
)

 

DRF(一)

原文:https://www.cnblogs.com/sima-3/p/11448976.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!