(一)drf 基础
全称: django-REST framework
接口: 什么是接口, restful 接口规范(协议)
CBV(基于 FBV 的基础上形成),CBV 生命周期源码 ---- 基于 restful 规范下的 CBV 接口
请求生命周期: 请求组件, 解析组件, 响应组件
序列化组件(序列化, 反序列化简单来说就是对象转为字符串, 字符串转为对象, 目的是为传输数据(传给别的语言或者存储))
三大认证(重中之重): 认证(用户是否合法), 权限(管理员, 普通用户), 频率(次数过多限制)
其他组件(过滤, 筛选, 排序, 分页, 路由)
1. 接口
概念: 联系两个物质的媒介, 完成信息的交互. 在 web 程序中, 联系前台页面与后台数据库的媒介.
Web 接口组成:
url: 长得像返回数据的 url 链接. 如 API.baidu.map/search
(www.baidu.com 不叫接口, 叫 url 链接, 访问只能拿到主页. API.baidu.map/search 是接口, 返回的是 JSON 数据)
请求参数: 前台按照指定的 key 提供数据给后台.(必须是给定的, 这样后台才能以此提取数据再到数据库查询返回)
响应数据: 后台与数据库交互后, 将数据反馈给前台.
因此, 接口就是带着请求参数访问能够得到响应数据的 url 链接.
接口 = url + 请求参数 + 响应数据
2.restful 接口规范
接口规范: 不同后台语言, 使用同样的接口返回同样的数据.
如何写接口: 要写 url 和响应数据. 如果将请求参数也加上, 就是在写接口文档.
两大部分:
(1)url
1)用 API 关键字标识接口 url. 方式 1:API.baidu.com; 方式 2:www.baudu.com/API
2)接口数据安全性决定优先选用 https 协议.
3)如果一个接口有多版本存在, 需要在 url 中标识体现. 如下的 v1 和 v2
API.baidu.com/v1/.... API.baidu.com/v2/....
4)操作中的数据称为资源, 在 url 中资源一般采用复数形式, 一个接口可以概括对该资源的多种操作方式.(一个 url 对应一个类, 类里面可以有多个请求方法)
可以对操作隐藏, 并且复用性更强 (写动作了, 只能适用这一个动作, 不写其他动作都可以用) 如 API.baidu.com/books API.baidu.com/books/(pk)
5)请求方式有多种, 用一个 url 处理如何让保证不混乱 ------ 通过不同的请求方式标识不同操作资源的方式
/books get 获取所有
/books post 增加一个(多个)
/books/(pk) delete 删除一个
/books/(pk) put 整体更新一个 #改一个用户
/books/(pk) patch 局部更新一个 #改一个用户的密码
6)资源往往涉及数据的各种操作方式: 筛选, 排序, 限制
API.baidu.com/books/?search = 宝马 & ordering=-price&limit=3
(2)响应数据
1)http 请求的响应会有响应状态码, 接口用来返回操作的资源数据, 也有自己操作数据结果的资源状态码(status 0 代表操作资源成功, 1 代表操作失败, 2 代表操作成功, 但没匹配结果)
注: 资源状态码和 http 状态码不一样, 为前后台的约定
2)资源状态码的文字提示.
status ok "账号有误或者密码有误"
3)资源本身
results
注: 删除资源成功不做任何数据返回(只返回空字符串, 连状态码, 状态信息都不返回)
4)不能直接返回的资源(子资源, 图片, 视频等资源), 返回该资源的 url 链接.
- https://api.baidu.com/v1/books?limit=3
- get|post|delete|put|patch
- {
- "status" : 0,
- "msg" : "ok",
- "results": [
- {
- "title": "三国",
- "price": 78,
- "img": "https://....."
- }
- ]
- }
3.django 流程
(1)项目准备:
1. 分发路由
在项目文件夹的 urls 复制一份到应用文件夹中. 然后在项目文件夹的 urls 分发路由给 App: 导入 include, 然后 url(r'^api/', include('api.urls')). 再在 App 文件夹的 urls.py 中分发路由给 CBV
2. 视图
在应用中分发路由前, 先写类视图
- from django.http import JsonResponse
- from django.views import View
- class Book(View):
- def get(self, request, *args, **kwargs):
- return JsonResponse('get ok', safe=False)
- def post(self, request, *args, **kwargs):
- return JsonResponse('get ok', safe=False) #safe 默认为 true, 要返回字典. 不是字典否则抛异常.
3. 在应用 urls 下分发路由
- from django.conf.urls import url
- from . import views #注意在应用中导入视图都是. 从当前应用中导入
- urlpatterns = [
- url(r'^books/', views.Book.as_view()),
- ]
4. 定义模型类
(1)models.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 = 'book' #自定义数据库表名
- verbose_name = "book" #给模型起个可读的名字, 默认是复数
- verbose_name_plural = verbose_name #取消上面的复数
- def __str__(self): #显示的内容
- return '<<%s>>' % self.title
(2)数据库迁移
进入 django 的 shell 环境中: Tools----> run manage.py task
在 shell 环境中生成迁移文件: makemigrations. 然后迁移: migrate
5. 生成 admin
(1)在 amin.py 中注册并且导入模型
- from django.contrib import admin
- port models
- admin.site.register(models.Book)
(2)创建用户
在 shell 环境中: createsuper 创建超级用户, 然后输入用户密码(邮箱不用)
(2)CBV 的请求生命周期
请求如何到 CBV 下的 get 和 post
a. 请求过来, 项目文件中路由分发给应用 API 的路由
b. 应用分发路由走 as_view 函数.
views.Book.as_view() 保存一系列数据 (request,args,**kwargs 等) 给 Book 对象, 然后都给 dispatch 进行路由分发.
dispatch 干的事: 判断请求方式是否支持, 然后返回 (通过 getattr) 支持的这些请求方法 (get,post 等, 在视图中自定义 get,post 的返回值) 的结果.
c. 通过 dispatch 就执行了 CBV 下请求方式的结果, 返回结果
4.django 原生的接口, 序列化
六大基础接口: 获取一个, 获取所有, 增加一个, 删除一个, 整体更新一个, 局部更新一个
十大接口: 6 大基础, 群增, 群删, 整体群改, 局部群改
1. 在应用的 urls.py 下分发路由 url(r'^books/$', views.Book.as_view()), # 必须要加 $,否则后面匹配不到 url(r'^books/(?P<pk>.*)/$', views.Book.as_view()), 有名分组 在视图函数中通过 kwargs.get(pk) 取到匹配的值
2. 在 views.py 里写逻辑 class Book(View):
def get(self, request, *args, **kwargs): pk = kwargs.get('pk') # 获取参数 if not pk: # 群查接口 # 操作数据库 book_obj_list = models.Book.objects.all() # 序列化过程 book_list = [] for obj in book_obj_list: # 将查到的对象序列化 dic = {} dic['title'] = obj.title dic['price'] = obj.price book_list.append(dic) return JsonResponse({ 'status' : 0, "msg" : "ok", "results": book_list, }, json_dumps_params={'ensure_ascii':False}) else: # 单查接口 book_dic = models.Book.objects.filter(pk=pk).values( 'title', 'price').first() if book_dic: return JsonResponse({ 'status': 0, "msg": "ok", "results": book_dic, }, json_dumps_params={'ensure_ascii': False})
return JsonResponse({ 'status': 2, "msg": "no results", }, json_dumps_params={'ensure_ascii': False})
def post(self, request, *args, **kwargs): # 前台通过 urlencoded 方式提交数据 try: book_obj = models.Book.objects.create(**request.POST.dict()) #create 创建对象。将 request.POST 中存放的提交的关键词参数转化为字典以 ** 方式传进去。没传参数,这边会报错。 if book_obj: return JsonResponse({ 'status': 0, "msg": "ok", “results”: {‘title’:book_obj.title, “price”:book_obj.price} }, json_dumps_params={'ensure_ascii': False}) except: # 健壮性 return JsonResponse({ 'status': 1, "msg": "wrong params", }, json_dumps_params={'ensure_ascii': False}) return JsonResponse({ # 可能操作数据库失败了 'status': 2, "msg": "created failed", }, json_dumps_params={'ensure_ascii': False})
|
JsonResponse 返回时, 中文会变成 unicode, 要加 json_dumps_params={'ensure_ascii':False}选项. 但在 Linux 环境下的火狐浏览器, 加了是乱码.
filter 返回 queryset 对象, 对象里是个列表(表名: 对象信息(有自定义 str 就是自定义的信息)).first 取里第一个对象(相当于 print(第一个对象))values 展示对应的对象里的值
- <QuerySet [<Book: <<三国演义>
- >>]> #直接. filter
- <<三国演义>
- > #.first()
- <QuerySet [{ 'title': '三国演义', 'price': Decimal( '56.00')}]>
- #.values('title','price') {'title': '三国演义', 'price': Decimal('56.00')}
- #.values.first() 是个字典
上面序列化的工作很麻烦. drf 就是为了方便序列化的.
postman 可以完成不同方式的请求: get,post,put 等
postman 发送数据包有三种方式: form-data,urlencoded,JSON. 原生 django 对 urlencoded 数据提交兼容.
来源: https://www.cnblogs.com/yq055783/p/13149575.html