APIview使用
- ModelVIewSet是对APIView封装
- ModelSerializer是对Serializer
1.1在user/urls.py中添加路由
urlpatterns=[
path('apiview/',views.UserInfoViewSet.as_view()),
]
1.2创建user/serializers.py写序列化器
- serializers.ModelSeralizer和serializers.Serializer field参数说明
'''field参数'''
#1.read_only
read_only=True #表示不允许用户自己上传,只能用于api的输出,序列化的时候也不用对这个数据进行验证,序列化返回是由改字段
#2.write_only
erite_only=True #表示在更新或创建实例时可以使用该字段,但在序列化返回时不包括该字段
#3.required:该字段时必需的,不能为空。
required=True #反序列化(前端返回数据必须包含此字段)的时候必须提供这个字段 设置False 可以不提供
# 4.allow_null/allow_blank:该字段允许为null/空
allow_null=True #可以为null,设置False则不能为null
# 5.label:标签,用于对字段显示设置
# 6.help_text:对字段进行解释的一段文本,用于提示
# 7.style:说明字段的类型
# 8.error_messages:字段出错时,信息提示
- 创建user/serializer.py写序列化器
#class User(AbstractUser):
# phone=models.CharField('手机号',max_length=20),
# img=models.ImageField(upload_to='user',null=True),
# nick_name=models.CharField('昵称',max_length=20),
# address=models.CharField('地址',max_lengthd=255),
class UserInfoSerilizer(serializers.Serializer):
id = serializers.CharField(read_only=True) # 普通字段,设置id为只读字段,不能修改
username = serializers.CharField(min_length=3,max_length=20,error_messages=
{'required': '该字段必填'}) # 显示普通字段
img = serializers.ImageField(required=False)
nick_name = serializers.CharField(max_length=20)
address = serializers.CharField(max_length=255)
xxx = serializers.SerializerMethodField(read_only=True) # 自定义显示(显示多对
多)
class Meta:
model = User
1.3 在 user/views.py 中添加视图函数
# 自定义显示 多对多 字段
def get_xxx(self,row):
'''row: 传过来的正是 User表的对象'''
users = row.username # 获取用户名
return users
# 定义创建语法:ser.save()执行,就会立刻调用create方法用来创建数据
def create(self, validated_data):
'''validated_data: 表单或者vue请求携带的json:
{"username":"zhangsan","password":"123456"}'''
# https://www.cnblogs.com/xiaonq/p/7978409.html
return User.objects.create(**validated_data)
# 定义更新方法
def update(self, instance, validated_data):
'''
instance : 查询的对象
validated_data : postman提交的json数据
{"username":"zhangsan","password":"123456"}
'''
if validated_data.get('username'):
instance.username = validated_data['username']
instance.save()
return instance
# 定义单一字段验证的方法
def validate_name(self, value):
if value == 'root':
raise serializers.ValidationError('不能创建root管理员账号')
return value
# 定义多字段验证方法
def validate(self, attrs):
print(attrs)
if attrs.get("username") == 'admin':
raise serializers.ValidationError('不能创建admin用户')
return attrs
from user.serializers import UserInfoSerializer
class UserInfoViewSet(APIView):
# 查询用户信息
def get(self, request, *args, **kwargs):
# 一对多、多对多查询都是一样的语法
obj = User.objects.all()
ser = UserInfoSerializer(instance=obj,many=True) # 关联数据多个
# ser = UserInfoSerializer(instance=obj[0]) # 关联数据一个
return Response(ser.data, status=200)
# 创建用户
'''创建用户'''
def post(self,request):
ser = UserInfoSerializer(data=request.data)
# 判断提交数据是否合法
if ser.is_valid():
ser.save()
2.测试接口
2.1 查询所有用户
2.2 创建用户
return Response(data=ser.data, status=201)
return Response(data=ser.errors,status=400)
# 更新用户信息
def put(self, request):
pk = request.query_params.get('pk')
try:
userinfo = User.objects.get(id = pk)
except Exception as e:
return Response(data='用户不存在', status=201)
# 创建序列化对象,并将要反序列化的数据传递给data构造参数,进而进行验证
ser = UserInfoSerializer(userinfo,data=request.data)
if ser.is_valid():
ser.save()
return Response(data=ser.data, status=201)
return Response(data=ser.errors,status=400)
测试接口
2.1查询所有用户
http://192.168.56.100:8888/user/apiview/
2.2创建用户
http://192.168.56.100:8888/user/apiview/
2.3跟新用户信息
http://192.168.56.100:8888/user/apiview/?pk=7
2.4限流功能测试
http://192.168.56.100:8888/user/apiview/
'''修改syl/settings.py配置限速设置'''
REST_FRAMEWORK = {
#3.1 限流策略
'DEFAULT_THROTTLE_RATES': {
'user': '3/hour', # 认证用户每小时10次
'anon': '3/day',
},
}d
1.RESTful风格API
详情查看博客地址:https://www.cnblogs.com/xiaonq/p/10053234.html
1.1 什么是RESTful
REST与技术无关,代表的是一种软件架构风格(REST是Representational State Transfer的简称,中
文翻译为“表征状态转移”)
REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识
所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资
源是REST区别与其他架构风格的最本质属性
对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:
Resource Oriented Architecture)
1.web开发本质
对数据库中的表进行增删改查操作
Restful风格就是把所有数据都当做资源,对表的操作就是对资源操作
在url同通过 资源名称来指定资源
通过 get/post/put/delete/patch 对资源的操作
2.RESTful API设计规范
1.API与用户的通信协议,总是使用HTTPs协议。
2.域名
3.版本
4. 面向资源编程 : 路径,视网络上任何东西都是资源,均使用名词表示(可复数)
5. method
1)子域名方式
https://api.example.com 尽量将API部署在专用域名(会存在跨
域问题)
https://www.example.com
2)url方式
https://example.org
https://example.org/api/ API很简单
URL,如:https://api.example.com/v1/
请求头 跨域时,引发发送多次请求
https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees
GET(查询数据) # 从服务器取出资源(一项或多项)
POST(创建数据) # 在服务器新建一个资源
PUT(修改数据) # 在服务器更新资源(客户端提供改变后的完整资源)
PATCH(修改属性) # 在服务器更新资源(客户端提供改变的属性)
DELETE(删除数据) # 从服务器删除资源
6. 过滤,分页,排序 :通过在url上传参的形式传递搜索条件
状态码
https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,
以及排序顺序
https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件
‘’‘1. 2XX请求成功’’’
200 请求成功,一般用于GET与POST请求
201 Created - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
‘’‘2. 3XX重定向’’’
301 NO CONTENT - 永久重定向
302 NO CONTENT - 临时重定向
‘’‘3. 4XX客户端错误’’’
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格
式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
‘’‘4. 5XX服务端错误’’’
500 INTERNAL SERVER ERROR - [*]:服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
更多状态码参考:https://www.runoob.com/http/http-status-codes.html
1.初始化VUE项目
#使用脚手架创建项目
vue init webpack deaxios
#进入项目
cd deaxios
#安装axios
cnpm install axios -S
#使用脚手架创建项目
vue init webpack deaxios
#进入项目
cd deaxios
#安装axios
cnpm install axios -S
在这里插入图片描述
2.封装axios
2.1 src 文件夹下新建http 文件夹,用来放网络请求相关的文件
2.2 src/http 文件夹下,创建 index.js 文件,对axios 进行封装
/* eslint-disable */
const { data } = require(‘autoprefixer’);
const axios = require(‘axios’);
const { error } = require(‘shelljs’);
axios.defaults.baseURL = ‘http://192.168.56.100:8888’ //vue请求后端地址
axios.defaults.timeout = 10000; // 超时设置
axios.defaults.withCredentials = true; // 跨域访问需要发送cookie时,一定要加上
axios.defaults.headers[‘Content-Type’] = ‘application/json’; //设置默认提交json
axios.defaults.transformRequest = data => JSON.stringify(data);//把数据对象序列化成json字符串
// 对请求拦截器,和响应拦截器进行封装
/*
请求拦截器,发送请求前需要调用这个函数
当没有登录时,直接跳转到登录页
请求发送前把token获取,设置到header中
*/
axios.interceptors.request.use(config=>{
//从localStorage中获取token
let token = localStorage.getItem(‘token’);
// 如果有token,就把token设置到请求头中Authorization字段中
token && (config.headers.Authorzation = token);
return config;
},error => {
return Promise.reject(error)
});
/*
响应拦截器,当后端返回数据给vue时,会调用这个函数
每次返回403错误时,跳转到login
*/
axios.interceptors.response.use(response =>{
//当响应码是2xx的情况时,进入这里
return response.data;
},error =>{
//当响应码不是2xx的情况是,进入这里
return error
});
//使用上面的axios对象,对get和post请求进行封装
/*
get方法,对应get请求
@param {String} url [请求的url地址]
@param {Object} params [请求时携带的参数]
*/
export function get(url,params,headers){
return new Promise((resolve,reject) =>{
axios.get(url,{params,headers}).then(res=>{
resolve(res.data.ResulObj)
}).catch(err =>{
reject(err.data)
})
})
}
/*
post方法,对应post请求
@param {String} url [请求的url地址]
@param {Object} params [请求时携带的参数]
*/
export function post(url,params,headers){
return new Promise((resolve,reject) =>{
axios.post(url,params,headers).then(res=>{
resolve(res.data)
}).catch(err =>{
reject(err.data)
})
})
}
//一定要导出函数
export default axios;
/* eslint-disable */
const { data } = require('autoprefixer');
const axios = require('axios');
const { error } = require('shelljs');
axios.defaults.baseURL = 'http://192.168.56.100:8888' //vue请求后端地址
axios.defaults.timeout = 10000; // 超时设置
axios.defaults.withCredentials = true; // 跨域访问需要发送cookie时,一定要加上
axios.defaults.headers['Content-Type'] = 'application/json'; //设置默认提交json
axios.defaults.transformRequest = data => JSON.stringify(data);//把数据对象序列化成json字符串
// 对请求拦截器,和响应拦截器进行封装
/*
请求拦截器,发送请求前需要调用这个函数
当没有登录时,直接跳转到登录页
请求发送前把token获取,设置到header中
*/
axios.interceptors.request.use(config=>{
//从localStorage中获取token
let token = localStorage.getItem('token');
// 如果有token,就把token设置到请求头中Authorization字段中
token && (config.headers.Authorzation = token);
return config;
},error => {
return Promise.reject(error)
});
/*
响应拦截器,当后端返回数据给vue时,会调用这个函数
每次返回403错误时,跳转到login
*/
axios.interceptors.response.use(response =>{
//当响应码是2xx的情况时,进入这里
return response.data;
},error =>{
//当响应码不是2xx的情况是,进入这里
return error
});
//使用上面的axios对象,对get和post请求进行封装
/*
get方法,对应get请求
@param {String} url [请求的url地址]
@param {Object} params [请求时携带的参数]
*/
export function get(url,params,headers){
return new Promise((resolve,reject) =>{
axios.get(url,{params,headers}).then(res=>{
resolve(res.data.ResulObj)
}).catch(err =>{
reject(err.data)
})
})
}
/*
post方法,对应post请求
@param {String} url [请求的url地址]
@param {Object} params [请求时携带的参数]
*/
export function post(url,params,headers){
return new Promise((resolve,reject) =>{
axios.post(url,params,headers).then(res=>{
resolve(res.data)
}).catch(err =>{
reject(err.data)
})
})
}
//一定要导出函数
export default axios;
2.3 ser/http 目录下创建 apis.js文件,用来写接口地址列表
/* eslint-disable */
//接口信息,生成请求方法
//引入 GET方法 ,POST方法
import {get,post} from './index'
//用户登录
export const login = (params,headers)=>post('/user/login/',params,headers)
//用户登录
export const login = (params,headers)=>post(’/user/login/’,params,headers)