1. Web应用模式
在开发Web应用中有两种应用模式 :
1. 前后端不分离 ( 混合开发 ) , 需要写模板 , 页面的渲染在服务器上完成 .
2. 前后端分离 , 只专注于写后端接口 , 返回JSON / XML数据 , 页面的渲染在浏览器完成 .
1.1 动/静态页面
动态页面 : 显示的内容却是可以随着时间 , 环境或者数据库操作的结果而发生改变的 .
静态页面 : , 无需经过服务器的编译 , 直接加载到客户浏览器上显示出
静态页面因为不需要而外的操作 , 所有请求速度快 .
大型的网站首页 , 会将动态的页面静态化 , 不需要每次都查询数据库 , 当数据发生了变化之后再次生成一个静态页面 .
1.2 前后端不分离
用户发送请求后得到的是模板语法渲染后的HTML页面 .
1. 3前后端分离
用户第一次访问的时候 , 被另一个静态文件服务接收 , 并放回一个静态页面 .
之后再基于静态页面的js代码向服务器发送请求 , 服务返回页面渲染需要的数据 , 静态页面拿到数据后渲染 .
1.4 JSON/XML数据格式
json格式占用的资源比xml少 .
1. json格式
* json使用的双引号
{
"name" : "kid" }
2. xml格式
< xml>
< name> kid</ name>
</ xml>
1.5 服务器页面后缀
根据请求内容动态地生成HTML , XML或其他格式文档的Web网页 , 返回给用户 ,
部分编程语言使用的框架返回的页面会携带一个标识后缀 .
java -- > jsp
https : / / xxx . xxx . xxx / xxx . jsp
php -- > php
http : / / xxx . xxx . xxx / xxx . php
Python -- > 没有
http : / / xxx . xxx . xxx / xxx
2. API接口
API接口 : 规定前后端信息交互规则 . 通过Web通信 , 也被称为Web API .
2.1 由来
为了形成共识 , 防止个人习惯引起的混乱 , 需要一套统一的接口规范 , 能让前后端写的接口用途一目了然 .
2.2 特点
* 1. url长得像返回数据的url链接
eg : 百度的api : http : / / api . map . baidu . com / place / v2 / search
* 2. 请求方式 : get , post , put , path , delete
* 3. 请求参数 : json或xml格式的key-value类型数据
* 4. 响应结果 : json或xml的数据
在浏览器中输入 : http : / / api . map . baidu . com / place / v2 / search 返回百度地址的API接口
AK参数是自定义的token
携带参数进行访问 :
AK = 6E823 f587c95f0148c19993539b99295
region = 上海
query = 肯得基
output = json
http : / / api . map . baidu . com / place / v2 / search?ak = 1 A43B68F2A55B3A07EB09E3B8303E5 : FG = 1 & region = 上海 & query = 肯得基 & output = json
3. Portman
Postman是一个用于构建和使用API的API平台 . 支持用户实时发送HTTP网页请求 , 帮助用户更好地搭建应用程序 ,
提高程序开发效率 , 同时软件内置了测试语言脚本 , 支持用户自定义测试脚本使用 .
3.1 下载
* 1. 下载地址 : https : / / www . Postman . com /
* 2. 点击下载
3.2 安装
* 1. 双击安装 , 没有配置可以选择 .
默认安装在 C : \ Users \ 用户 \ AppData \ Local \ Postman
* 2. 进入软件界面
3.3 建立连接
* 1. 新建请求
* 2. 选择请求方式
* 3. 请求参数 请求头 请求体的设置
* 4. 新建一个收藏目录
* 5. 在目录下添加请求
* 6. 收藏目录具备的功能
没有可用的API就不测试运行了
3.4 导出与导入
在测试的时候可以将请求收藏目录导出成一个文件 , 可以将文件发给自己合作伙伴 , 对方将文件导入即可使用 .
1. 导出
* 1. 导出请求文件
* 2. 选择位置保存
2. 导入
* 3. 选择导入
* 2. 选择上传文件
* 3. 找到文件 , 点击确定
* 4. 导入预览 , 点击导入
* 5. 导入成功
4. Restful规范
4.1 简介
REST : 全称Rpsentaional State Transfer , 表特征状态转移 .
Restful 是一种定义Web API接口的设置风格 , 适用于前后端分离的应用模式 .
可以在任何框架实现符合Restful规范的API接口 .
4.2 规范
Restful拥有 10 条规范 :
* 1. 数据安全保障 : url链接一般采用https协议进行传输 . https可以提高数据交互过程中的安全性 .
http 和 不加密的json格式被抓包工具 ( fiddler , charles . . . ) 捕获数据后很容易被解析出来 .
* 2. 接口的特征表现 : 一看就知道是API接口
https : / / api . baidu . com
https : / / www . baidu . com / api
在路由或域名中携带api字眼
* 3. 多数据版本共存 : 项目后续可能升级 , 之前的API接口 , 某些客户端可能在使用 , 另外开设API接口 .
在url链接中标识数据的版本 :
https : / / api . baidu . com / v1
https : / / api . baidu . com / v2
url链接v1 , v2就是不同数据版本的体现 , 只有在获取同一种资源下有多版本的情况 .
动词不使用 , 但利用请求方式去描述了需要操作的动词 .
* 4. 数据及资源 , 路径均使用名称 ( 一般提倡资源使用复数形式 )
接口一般都是完成前后端数据的交互 , 交互的数据称之为资源
https : / / api . baidu . com / users
https : / / api . baidu . com / books
在url链接中 , 尽量不要出来资源的动词 , eg : get_books , del_books . . .
特殊的接口可以出现动词 , 这些接口没有明确的资源 , 或这个动词就是接口的核心含义 .
https : / / api . baidu . com / place / search
https : / / api . baidu . com / login
* 5. 资源操作由请求方式决定 ( method )
操作资源一般都会涉及增删改查 , 通过不同的请求方式来标识这些动作 .
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 / post请求 : 修改主键为 1 的书籍
https : / / api . baidu . com / books / 1 put请求 : 整体修改主键为 1 的书籍
https : / / api . baidu . com / books / 1 patch请求 : 局部修改主键为 1 的书籍
https : / / api . baidu . com / books / 1 delete请求 : 删除主键为 1 的书籍
* 6. 过滤 , 通过在url中传递参数的形式 , 携带搜索条件
https : / / ap1 . xxx . com / v1 / books?limit = 10 指定返回数据的数量
https : / / ap1 . xxx . com / v1 / books?offset = 10 指定返回记录的开始位置 , ( 获取了 10 条数据 , 再向前偏移 10 )
https : / / ap1 . xxx . com / v1 / books?page = 2 & per_page = 100 指定第几页 , 以及每条的记录数
https : / / api . xxx . com / v1 / books?sortby = name & order = asc 指定返回结果安装哪个属性排序 , 及排序方式
https : / / ap1 . xxx . com / v1 / books?book_id = 1 指定筛选条件
* 7. 响应状态码
正常响应 : 响应状态码 2 xx
200 常规请求
201 创建数据成功
重定向响应 : 响应状态码 3 xx
301 永久重定向
302 展示重定向
客户端异常 : 响应状态码 4 xx
403 请求无权限
404 请求路径不存在
405 请求路径存在 , 但是请求的方法不存在
服务器异常 : 响应状态码 5 xx
500 服务器异常
* 8. 错误处理 , 因该放回错误信息 , error作为key
{
error : '无权限操作!'
}
* 9. 返回结果 , 针对不同的操作 , 服务器想用户返回非结果符合以下规范 :
GET / books 返回资源对象的列表或者数组
GET / books / 1 返回单个资源对象
POST / books 返回新生成的对象资源
PUT / books / 1 返回完整的资源对象
PATCH / books / 1 返回完整的资源对象
DELETE / books / 1 返回一个空文档
* 10. 需要url请求的资源 , 需要返回资源的请求资源
返回结果在家哦你提供链接 , 连向其他API方法 , 使得用户不查文档 , 也知道下一步需要做什么
{
"code" : 200 ,
"msg" : "ok" ,
" results : [
{
"name" : "开局签到荒古圣体" ,
"img" : "https://image.novels.com/books/cover.png"
}
. . .
]
}
5. DRF安装与使用
全称 : djangorestframework 是基于Django框架 , 用于快速构建Web Restful API的工具 .
新建一个Django项目 , 模板目录路径报错问题 .
5.1 安装
使用 3.10 .3 版本
pip3 . 6 install djangorestframework = = 3.10 .3
5.2 使用
* 1. 项目配置文件的INSTALLED_APPS属性中注册rest_framworh
'rest_framework' ,
* 2. 在app01下的models . py文件中创建一个映射表关系的类
from django. db import models
class Book ( models. Model) :
title = models. CharField( max_length= 32 , verbose_name= '书名' )
price = models. DecimalField( max_digits= 5 , decimal_places= 2 )
author = models. CharField( max_length= 32 , verbose_name= 32 )
* 3. 生成表
1. 生成表记录 : python3 . 6 manage . py makemigrations
2. 数据库迁移命令 : python3 . 6 manage . py migrate
* 4 . 在tests. py测试文件中 写入两条数据
import os
import sys
if __name__ == "__main__" :
os. environ. setdefault( "DJANGO_SETTINGS_MODULE" , "django_drf_01.settings" )
import django
django. setup( )
from app01. models import Book
queryset_list = [ ]
data_list = [ {
'title' : '开局签到荒古圣体' , 'price' : 123.12 , 'author' : 'kid' } ,
{
'title' : '开局签到五费卡' , 'price' : 321.21 , 'author' : 'qq' } ]
for dic in data_list:
book_obj = Book( ** dic)
queryset_list. append( book_obj)
Book. objects. bulk_create( queryset_list)
不想敲代码就手动输入
Navicat 快速打开sqlite3的文件
* 4 . 在应用app01下创建一个ser . py 文件 序列化表
from rest_framework. serializers import ModelSerializer
from app01. models import Book
class BookModelSerializer ( ModelSerializer) :
class Meta :
model = Book
fields = "__all__"
* 5. 写地址book的路由
from django. conf. urls import url
from django. contrib import admin
from app01 import views
from rest_framework. routers import DefaultRouter
router = DefaultRouter( )
print ( router)
router. register( 'books' , views. BooksViewSet)
urlpatterns = [
url( r'^admin/' , admin. site. urls) ,
]
* 5. 写BooksViewSet的视图函数
from rest_framework. viewsets import ModelViewSet
from . models import Book
from . ser import BookModelSerializer
class BooksViewSet ( ModelViewSet) :
queryset = Book. objects. all ( )
serializer_class = BookModelSerializer
class BooksViewSet ( ModelViewSet ) :
ModelViewSet 继承 GenericViewSet 继承 views . APIView 继承 View
* 6. 启动Django
在浏览器中输入 127.0 .0 .1 : 8000
* 7. 在浏览器中输入 127.0 .0 .1 : 8000 /books 或点击上图中的返回链接 , 返回含义json格式数据的页面 .
127.0 .0 .1 : 8000 /books/ 1 查询主键为 1 书籍的信息
127.0 .0 .1 : 8000 /books/ 2 查询主键为 2 书籍的信息
5.3 Postman连接
部分起你去Postman可能不支持重定向操作 , 就手动在后面加上 /
Django让请求端加 / 后再次请求 , Django能操作浏览的url , 操作不动Postman . . .
1. 查
提交post请求返回json格式的数据
127.0 .0 .1 : 8000 /books/
127.0 .0 .1 : 8000 /books/ 1 /
127.0 .0 .1 : 8000 /books/ 2 /
2. 删
提交delete请求 , 删除数据返回空
127.0 .0 .1 : 8000 /books/ 1 /
3. 改
提交put请求 , 返回数据对象
提交数据选择body , 点击raw , 选择JSON格式数据
127.0 .0 .1 : 8000 /books/ 2 /
{
"id" : 2 ,
"title" : "开局签到金克斯" ,
"price" : "12.30" ,
"author" : "qq"
}
返回的信息
4. 增
提交post请求 , 返回新增的对象
提交数据选择body , 点击raw , 选择JSON格式数据
127.0 .0 .1 : 8000 /books/
{
"title" : "Python入门到放弃" ,
"price" : "66.6" ,
"author" : "kid"
}
6. Dajngo View源码解析
CBV视图类必须继承View
Python下载的模块Python的lib / site-packages下
在看源码的时候可以打开展示组成部分 , 代开之后 , py文件可以展示函数 , 类 . .
在源码中会看见一些函数名点属性的情况 , 那么在这说明一下 , Python中一切皆对象 ,
只要对象有 . __setattr__方法就可以拥有属性 , 即可以存储值 , 那么对象有 . __getattr__便可以取值 .
def func2 ( ) :
pass
func2. x = 1
print ( type ( func2) , func2. x)
"""
func即是函数内存地址也是一个function类,
func.属性 = 值
.属性会执行类中__setattr__方法, 函数是由关键字def构建的, 这个__setattr__方法无法看见
只需要知道可以这样操作即可
"""
查看源码先将展示组成部分打开 , 方便查找 .
* 1. 写一个路由
url( r'^books2/' , views. Books2. as_view( ) ) ,
* 2. 视图类
from django. views import View
from django. shortcuts import HttpResponse
class Books2 ( View) :
def get ( self, request) :
return HttpResponse( 'OK' )
url ( r '^books2/' , views . Books2 . as_view ( ) )
url的第二个参数是一个函数的内存地址 ,
那么Books2 . as_view执行之后肯定得到一个函数的内存地址 .
在Books2中没有写 . as_view方法 , 那么就去父类中查找 , 父类View中有该方法 .
View文件所在文件 :
C : \ Users \ 用户名 \ AppData \ Roaming \ Python \ Python36 \ site-packages \ django \ views \ generic \ base . py
class classonlymethod ( classmethod ) :
. . .
@classonlymethod
def as_view ( cls, ** initkwargs) :
. . .
url ( r '^books2/' , view ( request ) )
路由匹配成功的时候 , 函数内存地址会加括号执行 , 并把request作为第一个参数进行传递
def view ( request, * args, ** kwargs) :
self = cls( ** initkwargs)
if hasattr ( self, 'get' ) and not hasattr ( self, 'head' ) :
self. head = self. get
self. request = request
self. args = args
self. kwargs = kwargs
return self. dispatch( request, * args, ** kwargs)
父类中有dispath方法
def dispatch ( self, request, * args, ** kwargs) :
if request. method. lower( ) in self. http_method_names:
handler = getattr ( self, request. method. lower( ) , self. http_method_not_allowed)
else :
handler = self. http_method_not_allowed
return handler( request, * args, ** kwargs)
父类中有http_method_names属性
http_method_names 在自己写的类中定义的话可以对请求进行限制 .
执行了方法之后 , 开始返回数据 .
7. DRF APIView源码解析
APIView是rest_framework的
导入 from rest_framework . views import APIView
* 1. 定义一个路由
url( r'^books3/' , views. Books3. as_view( ) ) ,
* 2. 定义视图类
from rest_framework. views import APIView
class Books3 ( APIView) :
def get ( self, request) :
return HttpResponse( 'OK' )
url ( r '^books3/' , views . Books3 . as_view ( ) )
那么Books3 . as_view执行之后肯定得到一个函数的内存地址 .
在Books2中没有写 . as_view方法 , 那么就去父类中查找 , 父类APIView中有该方法 .
APIView的中有通过super ( ) . as_view ( * * initkwargs ) 去拿到View的as_view方法 , 得到一个view函数的内存地址 .
class APIView ( View) :
. . .
@classmethod
def as_view ( cls, ** initkwargs) :
if isinstance ( getattr ( cls, 'queryset' , None ) , models. query. QuerySet) :
. . .
view = super ( ) . as_view( ** initkwargs)
view. cls = cls
view. initkwargs = initkwargs
return csrf_exempt( view)
局部禁用csrf检验在函数上加 @ csrf_exempt
@csrf_exempt
def func ( request) :
. . .
还有一种写法 , 在路由中局部添加禁用csrf装饰器
from django. views. decorators. csrf import csrf_exempt
url( '^test/' , csrf_exempt( views. test) ) ,
APIView文件所在位置 :
D : \ Python \ Python3 . 6 \ Lib \ site-packages \ rest_framework \ views . py
只要继承了APIView , 执行as_views ( ) , 在父类的基础上添加了添加scrf_exempt装饰器去除csrf检验
拿到vies函数名后加括号调用
vies ( ) -- > View的执行as_views的vies函数
def view ( request, * args, ** kwargs) :
self = cls( ** initkwargs)
if hasattr ( self, 'get' ) and not hasattr ( self, 'head' ) :
. . . 这里没什么不看了. . .
return self. dispatch( request, * args, ** kwargs)
Books3中没有dispatch方法去父类APIView中查找
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 ha ndling.
"""
self. args = args
self. kwargs = kwargs
request = self. initialize_request( request, * args, ** kwargs)
self. request = request
self. headers = self. default_response_headers
try :
self. initial( request, * args, ** kwargs)
if request. method. lower( ) in self. http_method_names:
handler = getattr ( self, request. method. lower( ) ,
self. http_method_not_allowed)
else :
handler = self. http_method_not_allowed
response = handler( request, * args, ** kwargs)
except Exception as exc:
response = self. handle_exception( exc)
self. response = self. finalize_response( request, response, * args, ** kwargs)
return self. response
8. DRF Request类
看下initialize_request是怎么样包装request的
def initialize_request ( self, request, * args, ** kwargs) :
parser_context = self. get_parser_context( request)
return Request(
request,
parsers= self. get_parsers( ) ,
authenticators= self. get_authenticators( ) ,
negotiator= self. get_content_negotiator( ) ,
parser_context= parser_context
)
class Request :
"""
Wrapper allowing to enhance a standard `HttpRequest` instance.
Kwargs:
- request(HttpRequest). The original request instance.
- parsers_classes(list/tuple). The parsers to use for parsing the
request content.
- authentication_classes(list/tuple). The authentications used to try
authenticating the request's user.
"""
def __init__ ( self, request, parsers= None , authenticators= None ,
negotiator= None , parser_context= None ) :
assert isinstance ( request, HttpRequest) , (
'The `request` argument must be an instance of '
'`django.http.HttpRequest`, not `{}.{}`.'
. format ( request. __class__. __module__, request. __class__. __name__)
)
self. _request = request
self. parsers = parsers or ( )
self. authenticators = authenticators or ( )
self. negotiator = negotiator or self. _default_negotiator( )
self. parser_context = parser_context
self. _data = Empty
self. _files = Empty
self. _full_data = Empty
self. _content_type = Empty
self. _stream = Empty
if self. parser_context is None :
self. parser_context = {
}
self. parser_context[ 'request' ] = self
self. parser_context[ 'encoding' ] = request. encoding or settings. DEFAULT_CHARSET
force_user = getattr ( request, '_force_auth_user' , None )
force_token = getattr ( request, '_force_auth_token' , None )
if force_user is not None or force_token is not None :
forced_auth = ForcedAuthentication( force_user, force_token)
self. authenticators = ( forced_auth, )
APIView文件所在位置 :
D : \ Python \ Python3 . 6 \ Lib \ site-packages \ rest_framework \ request . py
from rest_framework. views import APIView
class Books3 ( APIView) :
def get ( self, request) :
print ( request, request. _request)
return HttpResponse( 'OK' )
那么使用request的方法会是怎么样的
没有不要这样去写 request . _request . method
class Books3 ( APIView) :
def get ( self, request) :
print ( request. method)
return HttpResponse( 'OK' )
被包装request有 . 属性那么可能写了__getattr__方法
def __getattr__ ( self, attr) :
try :
return getattr ( self. _request, attr)
except AttributeError:
return self. __getattribute__( attr)
Request类将所有的post请求数据都封装到data属性中 .
from rest_framework. views import APIView
class Books3 ( APIView) :
def get ( self, request) :
print ( request. method)
return HttpResponse( 'OK' )
def post ( self, request) :
print ( request. data)
return HttpResponse( 'OK' )
data是一个静态方法
get请求 , 地址中的参数 request . query_params
print ( request . GET )
from rest_framework. views import APIView
class Books3 ( APIView) :
def get ( self, request) :
print ( request. query_params)
return HttpResponse( 'OK' )
APIView的initial方法
def initial ( self, request, * args, ** kwargs) :
self. perform_authentication( request)
self. check_permissions( request)
self. check_throttles( request)
9. 读源码总结
CBV源码分析 :
1. 视图类 , 必须继承Django的View类
2. 类中支持多种请求方式 , get , post , put , delete , . . . 请求来执行对应的方法
3. Django程序执行到 views . 类 . as_views ( ) , 立刻执行as_views ( ) 方法 , 自己的类中没有去父类View中找
4. 最后一个view闭包函数的内存地址
5. 请求的路由匹配成功 view加括号调用 , 并把第request作为第一个参数传入
6. view ( request ) 执行 -- > 通过闭包函数的特性拿到类名 , 类名加括号生成一个对象 , 对象 . dispatch ( )
7. 自己写的类没有 . dispatch ( ) 方法去父类Django的View类中查找
8. dispatch方法将请求转为小写 , 在去判断请求是否在属性http_method_names列表中
9. 自己写的类中没有http_method_names属性去父类Django的View类中查找
10. 如果请求满足条件 , 通过反射获取请求的方法 , 再加括号执行 , 并且将request传入 .
APIView源码解析 :
1. 视图类 , 继承DRF的APIView , APIView继承Django的View
2. 类中支持多种请求方式 , get , post , put , delete , . . . 请求来执行对应的方法
3. Django程序执行到views . 类 . as_views ( ) , 立刻执行as_views ( ) 方法 , 自己的类中没有去父类APIView中找
4. APIView中as_views ( ) 继承Django的View类的as_views ( ) 方法 , 得到一个view闭包函数
在为这个闭包函数加上一个装饰器器去除csrf校验
5. 请求的路由匹配成功 view加括号调用 , 并把第request作为第一个参数传入
6. view ( request ) 执行 -- > 通过闭包函数的特性拿到类名 , 类名加括号生成一个对象 , 对象 . dispatch ( )
7. 自己写的类没有 . dispatch ( ) 方法去父类DRF的APIView类中查找
8. dispatch方法
8.1 将request重新封装 , 得到一个新的request
8.2 异常捕获下面代码
8.3 加上三大认证模块
8.4 再将请求转为小写 , 在去判断请求是否在属性http_method_names列表中自己写的类中没有 http_method_names属性去父类DRF的APIView类中查找 , 还没有则去Django的View中找
8.5 如果请求满足条件 , 通过反射获取请求的方法 , 再加括号执行 , 并且将重新封装的request传入 .
8.6 将对应请求方法执行的结果赋值给response
8.7 将异常的结果赋值给response
8.8 渲染模块 , 浏览访问访问什么样的数据格式 , Pastman访问返回什么样的数据
* 注意点视图类的request是DRF的APIView类中的方法重新封装的 , 使用方法与原来一模一样 ,
所有的post请求数据被封装到data属性中 , 以字典的形式表示 .
10 练习
新建一个图书表 , 写 5 个符合restful规范的接口 , 用CBV的APIView实现 .
10.1 创建环境
* 1. 写路由
from django. conf. urls import url
from django. contrib import admin
from app01 import views
from django. views. decorators. csrf import csrf_exempt
urlpatterns = [
url( r'^admin/' , admin. site. urls) ,
url( r'^api/books/v1/' , scrf_exempt( views. Book. as_view( ) ) ,
]
* 2. 写CBV视图类
from django. shortcuts import render
from django. http import JsonResponse
from django. views import View
import json
from app01 import models
class Book ( View) :
def get ( self, request) :
pass
def post ( self, request) :
pass
def put ( self, request) :
pass
def patch ( self, request) :
pass
def delete ( self, request) :
pass
* 3. 模型中写映射表关系的类
from django. db import models
class Book ( models. Model) :
title = models. CharField( max_length= 32 , verbose_name= '书名' )
price = models. DecimalField( max_digits= 5 , decimal_places= 2 , verbose_name= '价格' )
author = models. CharField( max_length= 32 , verbose_name= '作者' )
def get_data ( self) :
book_dict = {
'id' : self. id ,
'title' : self. title,
'price' : float ( self. price) ,
'author' : self. author
}
return book_dict
* 4. 生成表
生成操作记录 python manage . py makemigrations
数据库迁移 python manage . py migrate
10.2 增
提交post请求 , 创建成功之后返回单个数据对象
提交地址 : 127.0 .0 .1 : 8000 /api/books/v1
提交数据格式json : ( id不需要提交 , json格式数据是双引号 )
{
"title" : "book1" ,
"price" : 123.1 ,
"author" : "aa"
}
django中的request . POST只能取到Content-Type ( 请求头 ) 为application / x-www-form-urlencoded ( form表单默认格式 ) 的数据,如果请求头为application / json ( json格式 ) ,multipart / form-data ( 文件 ) 等格式无法取到,只有在request . body里面能取到原生的数据。当发送过来的是JSON数据是,request . POST取到的数据是空的,这时只有用request . body取,再反序列化才能使用。
def post ( self, request) :
post_data = json. loads( request. body)
book_obj = models. Book. objects. filter ( pk= 1 ) . first( )
back_dic = {
'code' : 201 ,
'msg' : '操作成功' ,
}
back_dic[ 'book_obj' ] = book_obj. get_data( )
print ( back_dic)
return JsonResponse( back_dic)
10.3 查
请求方式get
127.0 .0 .1 : 8000 /api/books/v1/ 获取所有的数据 数据为一个列表套字典 , js的元组套对象 .
定义一个函数去处理路由的数据 , 获取路由中的主键
def get_id ( request) :
path = request. path
path_list = path. split( '/' )
for i in path_list:
if not i:
path_list. remove( i)
* _path, book_id = path_list
return book_id
class Book ( View) :
def get ( self, request) :
book_id = get_id( request)
back_dic = {
'code' : 200 ,
'msg' : '查询成功' ,
}
if book_id. isdigit( ) :
book_obj = models. Book. objects. filter ( pk= book_id) . first( )
back_dic[ 'book_obj' ] = book_obj. get_data( )
else :
book_obj = models. Book. objects. all ( )
book_obj_list = [ ]
for obj in book_obj:
print ( obj)
book_obj_list. append( obj. get_data( ) )
back_dic[ 'book_obj' ] = book_obj_list
print ( back_dic)
return JsonResponse( back_dic)
10.3 改
提交put请求 , 创建成功之后返回单个数据对象 修改数据以路由中的之间为主
提交地址 : 127.0 .0 .1 : 8000 /api/books/v1/ 1 /
提交数据格式json : ( id不需要提交 , json格式数据是双引号 )
def post ( self, request) :
post_data = json. loads( request. body)
book_obj = models. Book. objects. filter ( pk= 1 ) . first( )
back_dic = {
'code' : 201 ,
'msg' : '操作成功' ,
}
back_dic[ 'book_obj' ] = book_obj. get_data( )
print ( back_dic)
return JsonResponse( back_dic)
def put ( self, request) :
book_id = get_id( request)
if book_id. isdigit( ) :
put_data = json. loads( request. body)
models. Book. objects. filter ( pk= book_id) . update( ** put_data)
book_obj = models. Book. objects. filter ( pk= book_id) . first( )
back_dic = {
'code' : 200 ,
'msg' : '查询成功' ,
}
back_dic[ 'book_obj' ] = book_obj. get_data( )
else :
back_dic = {
'code' : 404 ,
'msg' : '路径不存在' ,
}
return JsonResponse( back_dic)
10.5 删
提交delete请求 , 删除成功之后返回空 , 删除数据以路由中的之间为主
提交地址 : 127.0 .0 .1 : 8000 /api/books/v1/ 1 /
提交数据格式json : ( id不需要提交 , json格式数据是双引号 )
def delete ( self, request) :
book_id = get_id( request)
if book_id. isdigit( ) :
num = models. Book. objects. filter ( pk= book_id) . delete( )
print ( num)
if num[ 0 ] :
back_dic = ''
return HttpResponse( back_dic)
back_dic = {
'code' : 404 ,
'msg' : '路径不存在!'
}
return JsonResponse( back_dic)