django-drf
1 restful 规范(建议)
API与用户的通信协议,总是使用HTTPS协议
域名规范
版本规范
路径,视网络上任何东西都是资源,均使用名词表示(可复数)
method
过滤,通过在url上传参的形式传递搜索条件
状态码
错误处理,应返回错误信息,error当做key。
返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范。
Hypermedia API,RESTful API最好做到Hypermedia,
即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。
3 认证流程原理
当用户进行登录的时候,运行了登录类的as_view()方法,
1、进入了APIView类的dispatch方法
2、执行了self.initialize_request这个方法,是重定义request,
并且得到了自己定义的认证类对象
3、执行self.initial方法中的self.perform_authentication,里面运行了user方法
4、再执行了user方法里面的self._authenticate()方法
5、然后执行了自己定义的类中的authenticate方法,
自己定义的类继承了BaseAuthentication类,里面有
authenticate方法,如果自己定义的类中没有authenticate方法会报错。
6、把从authenticate方法得到的user和auth赋值给user和auth方法
7、这两个方法把user和auth的值赋值给了request.user:
是登录用户的对象,request.auth:是认证的信息字典
4 、drf组件权限的实现过程?
当用户执行一个业务的时候,运行了as_view方法
1、进入了APIView类的dispatch方法
2、进入self.initial方法中的self.check_permissions(request)方法
3、里面执行了for循环,把每个权限类实例化对象,
4、执行自己定义的权限类里面的has_permission方法,里面会判断request.user是否存在
5、不存在就返回False,存在就返回True
6、之后执行self.permission_denied报错方法,返回的是False就报错,
可以自定义报错信息,在has_permission方法中
写message = {"status": False, "error": "登录成功之后才能评论"},
就实现了自定义报错
7、如果返回的是True就让他进入功能
5 drf组件中节流的实现方式?
匿名用户通过ip地址来控制访问频率,已登录用户通过id来控制
首先要设置配置文件:
# 也可以设置全局,
"DEFAULT_THROTTLE_CLASSES":["rest_framework.throttling.AnonRateThrottle",]
# 设置访问频率——一分钟10次
"DEFAULT_THROTTLE_RATES": {
"anon":"10/m"
}
- 实现原理
把所有登录记录时间放在一个列表中,当用户请求网页的时候,
用现在的时间减去约束的时间间隔,然后把小于这个时间记录排除,
再计算出时间间隙的记录条数,
如果其中的条数小于规定的条数则可以访问并且把当前时间添加进列表中,
如果大于或等于则不让其访问。
- 具体流程
当用户请求网页的时候,后台允许该界面的url中的as_views(),
运行源码的APIView中的dispatch方法,运行initial方法,里面的check_throttles方法,
循环运行节流类中的allow_request方法,但是AnonRateThrottle等类中没有,
去执行SimpleRateThrottle类中的allow_request方法,里面就是实现原理中的代码,
如果可以访问返回True,如果不让访问则返回False,之后返回check_throttles
,如果是False则运行SimpleRateThrottle类中的wait方法得到需要等待的时间在页面上显示!
6 什么是jwt? 它的优势是什么?
jwt的全称是json web token, 一般用于用户认证
jwt的实现原理:
- 用户登录成功之后,会给前端返回一段token。
- token是由.分割的三段组成。
- 第一段header:类型+算法+base64url加密
- 第二段paylod:用户信息+超时时间+base64url加密
- 第三段sign:hs256(前两段拼接)加密 + base64url
- 以后前端再次发来信息时
- 超时验证
- token合法性校验
优势:
- token只在前端保存,后端只负责校验。
- 内部集成了超时时间,后端可以根据时间进行校验是否超时。
- 由于内部存在hash256加密,所以用户不可以修改token,只要一修改就认证失败。
7 drf 都继承过什么类
APIView
ModelViewSet
8 10大组件
版本 *
解析器 *
序列化 ****
分页 ***
路由 **
视图 **
渲染器 *
认证
权限
节流
9 版本配置
url路径传参
urlpatterns = [
...
url(r'^(?P<version>[v1|v2]+)/publishers/$', views.PublisherViewSet.as_view({'get': 'list', 'post': 'create'})),
]
REST_FRAMEWORK = {
# 配置默认使用的版本控制类
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
'DEFAULT_VERSION': 'v1', # 默认的版本
'ALLOWED_VERSIONS': ['v1', 'v2'], # 有效的版本
'VERSION_PARAM': 'version', # 版本的参数名与URL conf中一致
}
获取版本 request.version
10 解析器
对请求体的具体数据进行解析
settings 文件配置
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.QueryParameterVersioning',
'DEFAULT_VERSION': 'v1',
'ALLOWED_VERSIONS': ['v1', 'v2'],
'VERSION_PARAM': 'version',
'DEFAULT_PARSER_CLASS': ['rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser'],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE':2
}
使用 request.data
11 序列化
对请求数据的验证
class AuthSerializer(serializers.Serializer):
# name这个字段跟数据库对应
name = serializers.CharField(error_messages={'required':'不能为空'})
class AuthView(APIView):
def post(self,request,*args,**kwargs):
ser = AuthSerializer(data=request.data)
if ser.is_valid():
print(ser.validated_data['name'])
else:
print(ser.errors)
return HttpResponse('提交数据')
对requestset进行序列化
写类
class RolesSerializer(serializers.Serializer):
# name这个字段跟数据库对应
name = serializers.CharField()
class OOSerializer(serializers.ModelSerializer):
class Meta:
model = models.MyModel
# fields = '__all__'
fields = ['name']
depth = 1 # 自动序列化连表
字段
name = serializers.CharField(source='xx.xx.xx')
gp = serializers.SerializerMethodField() # 自定义显示
# 自定义方法
def get_gp(self,row):
role = row.roles.all()
ret = []
for item in role:
ret.append({'id':item.id,'title':item.title})
return ret
生成链接
group = serializers.HyperlinkedIdentityField(view_name='gp',
lookup_field='group.id',lookup_url_kwarg='xxx')
12 分页
from rest_framework.views import APIView
from rest_framework.response import Response
from api import models
from api.utils.serializsers.pager import PagersSerialiser
from rest_framework.pagination import PageNumberPagination
class UserView(APIView):
def get(self,request,*args,**kwargs):
# 获取所有数据
users = models.UserInfo.objects.all()
# 创建分页对象
pg = PageNumberPagination()
# 在数据库获取分页的数据
pager_user = pg.paginate_queryset(queryset=users,request=request,view=self)
# 对数据进行序列化
ser = PagersSerialiser(instance=pager_user,many=True)
return Response(ser.data)
13 视图
完成增删改查 ModelViewSet
完成增删 CreateModelMixin,DestroyModelMixin,GeneralViewSet
完成复杂的逻辑 GeneralViewSet 或者 APIView
路由
url(r'^new/index/$', views.NewIndexView.as_view({'get':'list','post':'create'}), ),
url(r'^new/index/(?P<pk>\d+)/',views.NewIndexView.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':'partial_update'}), ),
视图
from rest_framework.viewsets import ModelViewSet
from api.utils.serializsers.pager import PagersSerialiser
class ViewView(ModelViewSet):
queryset = models.UserInfo.objects.all()
serializer_class = PagersSerialiser
pagination_class = PageNumberPagination
14 路由
a.
url(r'^(?P<version>[v1|v2]+)/new/index/$', views.NewIndexView.as_view({'get':'list','post':'create'}), ),
b.
url(r'^(?P<version>[v1|v2]+)/new/index/$', views.NewIndexView.as_view(), ),
c.
自动生成路由
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'xxoo',views.ViewView)
url(r'^(?P<version>[v1|v2]+)/',include(router.urls))
15 渲染器

浙公网安备 33010602011771号