restful
一个url路由 对应一个功能,操作,绝大多数的操作都是针对数据库的增删改查
前后端分离,都是ajax axios,所有的接口都是接收json,返回json
Api 接口是提供给程序访问的 ,提供了权限和限流认证
restful 携带token 需要在请求头中 用键值对的方式携带token
可以通过restful-jwt 提供的认证视图来处理 用户认证
认证和权限
可以自定义权限类视图 需继承BasePermission权限类
进入IsAuthenticated 更改认证条件
class MyPermission(BasePermission):
def has_permission(self,request,view):
return bool(request.user and request.user.is_superuser)
权限和限流
在 app.urls中配置路由
from rest_framework_jwt.views import obtain_jwt_token
path('login/', obtain_jwt_token)
在settings.py中配置 权限认证配置
REST_FRAMEWORK = {
# 限流限制
'DEFAULT_THROTTLE_RATES': {
'user': '10/hour',
'anon': '5/day'
},
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_jwt.authentication.JSONWebTokenAuthentication' # 接口的认证器
]
}
JWT_AUTH = {
'JWT_PAYLOAD_HANDLER': 'rest_framework_jwt.utils.jwt_payload_handler',
# headers中 Authorization键对应的值得前缀 类似于 : jwt xxxxxx
'JWT_AUTH_HEADER_PREFIX': 'JWT',
# 有效期7天
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
# 允许刷新
'JWT_ALLOW_REFRESH': True,
# token在24小时过期
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(hours=24)
}
permission_classes = (AllowAny,) # 处理权限的类 ,允许所有人访问
permission_classes = (IsAuthenticated,) # 处理权限的类 ,允许认证用户访问
throttle_classes = [AnonRateThrottle] # 处理接口的限流
在settings.py中配置限流次数
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES':{
'user':'10/hour',
'anon':'5/day'
}
}
# 函数视图
def book_view(request):
if request.method == 'GET':
books = BookInfo.objects.all()
book_list = []
for book in books:
# 组装数据
book_data = {
'id': book.id,
'btitle': book.btitle,
'bpub_date': book.bpub_date,
'bread': book.bread,
'bcomment': book.bcomment
}
book_list.append(book_data)
return JsonResponse(book_list, safe=False)
if request.method == 'POST':
# 从请求获取数据
btitle = request.POST.get('btitle')
bpub_date = request.POST.get('bpub_date')
bread = request.POST.get('bread')
bcomment = request.POST.get('bcomment')
if all([btitle, bpub_date]):
pass
else:
return JsonResponse({'code': 400, 'msg': '缺少参数'})
# 根据数据创建模型
book = BookInfo.objects.create(btitle=btitle, bpub_date=bpub_date)
# 校验数据
book.save()
# 组装数据
book_data = {
'id': book.id,
'btitle': book.btitle,
'bpub_date': book.bpub_date,
'bread': book.bread,
'bcomment': book.bcomment
}
return JsonResponse(book_data)
# 类视图
class BookView(View):
def get(self, request):
books = BookInfo.objects.all()
book_list = []
for book in books:
# 组装数据
book_data = {
'id': book.id,
'btitle': book.btitle,
'bpub_date': book.bpub_date,
'bread': book.bread,
'bcomment': book.bcomment
}
book_list.append(book_data)
return JsonResponse(book_list, safe=False)
def post(self, request):
# # 从请求获取数据
# btitle = request.POST.get('btitle')
# bpub_date = request.POST.get('bpub_date')
# bread = request.POST.get('bread')
# bcomment = request.POST.get('bcomment')
# 从body中获取数据
data = json.loads(request.body.decode())
btitle = data.get('btitle')
bpub_date = data.get('bpub_date')
if all([btitle, bpub_date]):
pass
else:
return JsonResponse({'code': 400, 'msg': '缺少参数'})
# 根据数据创建模型
book = BookInfo.objects.create(btitle=btitle, bpub_date=bpub_date)
book.save()
book_data = {
'id': book.id,
'btitle': book.btitle,
'bpub_date': book.bpub_date,
'bread': book.bread,
'bcomment': book.bcomment
}
return JsonResponse(book_data)
# APIView
class BookAPIView(APIView):
# permission_classes = (AllowAny,) # 处理权限的类 ,允许所有人访问
permission_classes = (IsAuthenticated,) # 处理权限的类 ,允许认证用户访问
throttle_classes = [AnonRateThrottle] # 处理接口的限流
def get(self, request):
books = BookInfo.objects.all()
book_list = []
for book in books:
# 组装数据
book_data = {
'id': book.id,
'btitle': book.btitle,
'bpub_date': book.bpub_date,
'bread': book.bread,
'bcomment': book.bcomment
}
book_list.append(book_data)
return Response(book_list)
def post(self, request):
# 从body中获取数据
btitle = request.data.get('btitle')
bpub_date = request.data.get('bpub_date')
if all([btitle, bpub_date]):
pass
else:
return Response({'code': 400, 'msg': '缺少参数'})
# 根据数据创建模型
book = BookInfo.objects.create(btitle=btitle, bpub_date=bpub_date)
book.save()
book_data = {
'id': book.id,
'btitle': book.btitle,
'bpub_date': book.bpub_date,
'bread': book.bread,
'bcomment': book.bcomment
}
return Response(book_data)
序列化器
如果使用serializers.Serializer 需要 字段名和模型中的字段名一致
写入时需重写create方法
当读取和写入数据共用一个序列化器时需要将写入不需要的字段添加 read_only = True
class BookSerializer(serializers.Serializer):
"""
字段名必须是模型中的字段名
"""
id = serializers.IntegerField(read_only=True)
btitle = serializers.CharField()
bpub_date = serializers.DateField()
bread = serializers.IntegerField(read_only=True)
bcomment = serializers.IntegerField(read_only=True)
def create(self, validated_data):
book = BookInfo(btitle=validated_data.get('btitle'), bpub_date=validated_data.get('bpub_date'))
book.save()
return book
使用serializers.ModelSerializer 模型序列化器时 只需指定需要序列化的model 和字段
class HeroWriteSerializer(serializers.ModelSerializer):
class Meta:
model = HeroInfo
# fields = '__all__' # 所有字段
# fields = ['id', 'btitle', 'bpub_date', 'bread', 'bcomment', 'is_delete'] # 指定要哪些字段
exclude = ['is_delete']
# 序列化数据 字符串 json
# 结构化数据 二维表,表,model
# 结构化 => 序列化 只需要指定 把结构化数据中的字段序列化
# 序列化 => 结构化 1.校验,数据是否符合结构需求。2.校验通过,把数据放在结构中(model) model.save()
模型序列化器外键所在表关联查询
使用 depth 深入序列化即可
class HeroSerializer(serializers.ModelSerializer):
class Meta:
model = HeroInfo
depth = 1 # 深入序列化一层
fields = '__all__' # 所有字段
主表反向查询子表数据
class BookHeroSerializer(serializers.ModelSerializer):
class Meta:
model = HeroInfo
exclude = ['hbook', 'is_delete']
class BookSerializer(serializers.ModelSerializer):
# 英雄信息同时读取
# 能序列化的内容,是模型所有的属性内容
# book = BookInfo()
# book.heroinfo_set
heroinfo_set = BookHeroSerializer(many=True)
class Meta:
model = BookInfo
fields = '__all__' # 所有字段
# fields = ['id', 'btitle', 'bpub_date', 'bread', 'bcomment', 'is_delete'] # 指定要哪些字段
# exclude = ['is_delete']
处理器
返回加工后的结果 或者报错
class BookWriteSerializer(serializers.ModelSerializer):
# 处理器=> 返回处理后的结果, 或者报错
def validate_btitle(self, data):
# 可以加工书名
# 验证书籍名, 条件: 不能是一个字
if len(data) > 1:
pass
else:
# raise serializers.ValidationError('书名不能是一个字') # 报错
return data+data # 加工
return data
class Meta:
model = BookInfo
fields = '__all__' # 所有字段
校验器 处理结果 1.不报错 2.报错
# 校验器 处理结果 1.不报错 2.报错
def btitle_validator(data):
if len(data) > 1:
pass
else:
raise serializers.ValidationError('书名不能是一个字') # 报错
def btitle_validator2(data):
if len(data) < 10:
pass
else:
raise serializers.ValidationError('书名不能超过10个字') # 报错
class BookWriteSerializer(serializers.ModelSerializer):
btitle = serializers.CharField(max_length=20, validators=[btitle_validator,btitle_validator2])
# validators 里面全是校验器,校验器函数,处理结果
class Meta:
model = BookInfo
fields = '__all__' # 所有字段
同时校验两个数据
class BookWriteSerializer(serializers.ModelSerializer):
# 同时校验多个数据
def validate(self, dates):
pw = dates.get('pw')
pw2 = dates.get('pw2')
if pw == pw2:
pass
else:
raise serializers.ValidationError('两次密码不一致') # 报错
return dates
class Meta:
model = BookInfo
fields = '__all__' # 所有字段