DAY 68 drf06

1 drf入门
-web开发模式:分离和混合
  -api接口:接口
   -postman的使用(http客户端)
   -restful-10条规范
   -drf是什么,能做什么(快速写符合resful规范的接口)
   -分析了执行流程:APIView
  -重写了dispatch
      -包装了新的request:drf的request
  -self.initial
      -请求格式处理,认证,权限,频率
  -处理了全局异常  
  -处理了响应
   -Request对象:data,取其他值和属性时跟原来一样
   
2 序列化器
-Serializer,ModelSerializer
   -写一个类继承Serializer
   -在类中写字段,
   -字段参数:read_only,write_only
   -视图类中使用:ser=Serilaizer(要序列化的对象,many=True)
   -ser.data
   -反序列化
   -ser=Serilaizer(data=字典)
   -ser.is_valid()
   -ser.save():Serializer需要重写update和create
   -反序列化的修改
   -ser=Serilaizer(instance=对象,data=字典)
   
   
   -ModelSerializer
   -class Meta:
  model=表模型
      fields='__all__'
  extra_kwargs={'name';{}}
   -重写字段
   name=serilaizer.CharField(source='xx')
   name=serilaizer.SerializerMethodField()
   def get_name(self,obj):
       return 'sb'+obj.name
   子序列化
   publish=PublishSerializer()
2.1 序列化类的源码
-many控制了谁
  -局部钩子和全局钩子
-source为什么填publish.name  方法
   
3 请求和响应
-自己封装了一个响应对象(low,高级)
  -通过配置,配置请求和响应(全局配置,局部配置)
   
4 视图
-APIView,GenericAPIView
  -5个视图扩展类
-9个视图子类
  -写一个删除接口(只需要继承DestroyAPIView,写上那两个类属性)
  -视图集
-ViewSetMixin:路由就不一样了

4.1 写一个删除接口,但是,删除后要记录日志

5 自动生成路由
-SimpleRouter
  -ViewSetMixin+9个子类视图才能自动生成路由
6 action装饰器
-自动生成路由后,使用action装饰器来继续让写在视图类的方法,可以被访问到

 

1 认证类前奏登录功能,认证类编写

1 认证类的使用流程
-写一个类,继承BaseAuthentication
-在类中写authenticate(self, request):
-在方法中进行校验,如果校验通过,返回两个值(返回空)
-使用认证类,在视图类上加
authentication_classes = [LoginAuth,]

 

1.1 登录功能

1.1.1 写两个表

##先写两个表
##models.py
class User(models.Model):
   name = models.CharField(max_length=32)
   password = models.CharField(max_length=32)


class UserToken(models.Model):
   user = models.OneToOneField(to='User',on_delete=models.CASCADE)
   token=models.CharField(max_length=32)
   
   
###登录功能

1.1.2 登录视图类

class UserView(ViewSetMixin, CreateAPIView):
   queryset = models.User.objects.all()
   serializer_class = serializer.UserModelSerializer
   authentication_classes = []

   #基于原生session版
   @action(methods=['POST'], detail=False)
   def login(self, request):
       username = request.data.get('username')
       password = request.data.get('password')
       user = models.User.objects.filter(name=username, password=password).first()
       request.session['name'] = user.name
       request.session['id'] = user.id
       print(type(request.session))
       request.session.save()
       print(request.session.session_key)
       from  django.contrib.sessions.backends.db import SessionStore
       if user:
           return APIResponse(msg='登录成功', token=request.session.session_key)
       else:
           return APIResponse(status=101, msg='用户名或密码错误')

   # 基于自己写的UserToken表版
   # @action(methods=['POST'], detail=False)
   # def login(self, request):
   #     username = request.data.get('username')
   #     password = request.data.get('password')
   #     user = models.User.objects.filter(name=username, password=password).first()
   #     token = uuid.uuid4() # 生成一个uuid的随机字符串
   #     # 这个是错误的:user.usertoken是None
   #     # user.usertoken.user=user
   #     # user.usertoken.token=token
   #     # 如果每次都是新增,如果它登录过,这个地方会报错
   #     # models.UserToken.objects.create(user=user,token=token)
   #     # 如果有就更新,如果没有就创建
   #     # 根据user去查询,如果能查到,就修改token,如果查不到,就新增一条
   #     models.UserToken.objects.update_or_create(defaults={'token': token}, user=user)
   #     if user:
   #         return APIResponse(msg='登录成功', token=token)
   #     else:
   #         return APIResponse(status=101, msg='用户名或密码错误')

1.1.3 路由

router = SimpleRouter()
router.register('user', views.UserView)

urlpatterns = [
   path('admin/', admin.site.urls),
   path('api/', include(router.urls)),
]

1.2 认证类

1.2.1 认证类的编写

####基于自己写的UserToken表
# class LoginAuth(BaseAuthentication):
#     def authenticate(self, request):
#         token = request.GET.get('token')
#         user_token = models.UserToken.objects.filter(token=token).first()
#         if user_token:
#             # 登录了
#             #返回两个值,第一个值,给了新的request对象的user属性,通常情况我们把当前登录用户给它
#             return user_token.user, ''
#         else:
#             raise AuthenticationFailed('您没有登录')


####基于session的
from django.contrib.sessions.models import Session
from importlib import import_module
from django.conf import settings
class LoginAuth(BaseAuthentication):
   def authenticate(self, request):
       token = request.GET.get('token')

       #通过传入的token(session_key,取到当前key的session对象)
       engine = import_module(settings.SESSION_ENGINE)
       self.SessionStore = engine.SessionStore
       request.session = self.SessionStore(token)

       Session.objects.filter(session_key=token).first()
       # print(request.session['name'])
       if request.session.get('name',None):
           print(request.session['name'])
           print(request.session['id'])
           return '',''
       else:
           raise AuthenticationFailed('您没有登录')

1.2.2 使用认证类(全局用,局部用)

#全局用,setting中配置(所有接口都需要认证)
REST_FRAMEWORK={
   "DEFAULT_AUTHENTICATION_CLASSES":["app01.auth.LoginAuth",]
}
# 登录功能需要局部禁用,在视图类中加入
authentication_classes = []
   
#只在局部使用,只在视图类中加
authentication_classes = [LoginAuth,]

 

 

2 认证的局部和全局使用

看上面

 

3 权限类编写和使用

3.1 编写权限类

class MyPermission(BasePermission):
message='你没有权限'
def has_permission(self, request, view):
if request.user.user_type == 1:

return True
else:
self.message='你是%s用户,你没有权限'%request.user.get_user_type_display()
return False

3.2 权限类的使用

# 局部使用(在视图类中加)
permission_classes = [MyPermission,]
# 全局使用(在配置文件中配置)
REST_FRAMEWORK={
"DEFAULT_PERMISSION_CLASSES":["app01.auth.MyPermission",],
}

 

4 频率类的使用

4.1 定义一个频率类

from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
class MyThrottle(SimpleRateThrottle):
scope = 'ip_th'
def get_cache_key(self, request, view):
return self.get_ident(request)

4.2 在配置文件中配置

REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'ip_th': '5/m', #一分钟访问5次
},
}

4.3 局部使用,全局使用

# 局部用,在视图类中配置
throttle_classes = [MyThrottle,]
# 全局用,在配置文件中配置
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_CLASSES": ["app01.auth.MyThrottle", ],
'DEFAULT_THROTTLE_RATES': {
'ip_th': '5/m', #一分钟访问5次
},

}

补充

1 魔法方法:类中以  __名字__的方法 
2 魔法方法的作用:某种情况下,会触发它的执行
-__init__,类实例化的时候
  -__call__,对象()
  -__getattr__,对象.属性
   新的request.method,通过反射区原来的request中取出来返回
   
   
   
3 猴子补丁:动态的把对象替换掉,以后用的都是新对象
原文地址:https://www.cnblogs.com/DEJAVU888/p/14893769.html