drf和channels的一点源码学习,Authentication,WebsocketConsumer

@api_view()

总所周知,drf的cbv的流程是:路由匹配>视图as_view>dispatch,然后对django原生进行扩展。

今天聊一下fbv。视图函数不用api_view()装饰器就是原生django视图,加了后就是drf的视图,那么,这个装饰器中必然调用了as_view或者dispatch。

装饰器 @api_view()里面进入了 drf的as_view()
在用 django 自己的路由与函数配合时不享有drf的request封装与验证等功能

例如:
urlpatterns = [
    path('hello/',views.hello),
]
普通django视图:
	def hello(request):
        print(request.user, request.auth) # 报错,查无此人
        return JsonResponse({'data':'hello_world'})
drf的函数视图:
	@api_view(('GET',))
    def hello(request):
        print(request.user, request.auth)
        return JsonResponse({'data':'hello_world'})

api_view装饰器

@api_view(['GET'])
@authentication_classes([SessionAuthentication, BasicAuthentication])
@permission_classes([IsAuthenticated])
def example_view(request, format=None):
    content = {
        'user': unicode(request.user),  # `django.contrib.auth.User` instance.
        'auth': unicode(request.auth),  # None
    }
    return Response(content)

action装饰器

@action(detail=False, methods=['GET'], permission_classes=[IsOwnerOrReadOnly], 
            authentication_classes=[UserTokenAuthentication])
def example_view(request, format=None):
    content = {
        'user': unicode(request.user),  # `django.contrib.auth.User` instance.
        'auth': unicode(request.auth),  # None
    }
    return Response(content)

@action()在cbv中使用,主要做了mapping,覆盖了类里面的那些authentication_classes等。
@api_view()在fbv中使用,主要将基于函数的视图转换为APIView子类,即进入drf的as_view()方法。

TokenAuthentication

class TokenAuthentication(BaseAuthentication)
	# 以此类为例,源码不难看懂
    def authenticate(self, request)
    # 此方法获取了 Authorization: Token 401f7ac837da42b97f613d789819ff93537bee6a
    # 验证了Token 格式
    def authenticate_credentials(self, key)
    # 调用了get_model方法,默认从rest_framework.authtoken.models拿Token表
    # 然后在表里取数据验证 Token,拿到对象返回元组分别被放到 request.user 和 request.auth
    def get_model(self):
        if self.model is not None:
            return self.model
        from rest_framework.authtoken.models import Token
        return Token

失败会抛异常 raise exceptions.AuthenticationFailed(msg)
	# 这之间有个 ugettext_lazy 惰性翻译的使用,有什么好处?
并最终 在入口函数 dispatch 中捕获异常
	  调用 handle_exception(self, exc) 方法将 信息Response

自己决定自定义或用自带的,我个人不喜欢用自带的,尤其是迁移它的表。

django channels

group_name 和 channel_name

  1. group是一个群,group_name是群名称,channel_name是一个成员。
  2. group_add 加群,group_discard 退群。
  3. 加群和退群不是下线,不是断开了websocket连接,大家还是都与服务器连接着的。
  4. group就是为了将消息发送给多个channel_name
  5. 示例 self.channel_name : specific.xHTtAqbH!rnadllzYyWck
    channel_name

AsyncJsonWebsocketConsumer

websocket是事件驱动的
1.建立连接2.接收消息3.发生错误4.关闭连接

对应到channels源码就三个方法
websocket_connect(self, message)
websocket_receive(self, message)
websocket_disconnect(self, message)

然后那些 receive(),receive_json(),connect(),disconnect()都只是被调用而已,所以重写它们也能完成逻辑,追根溯源直接重写websocket_receive才是最灵活的。

class AsyncJsonWebsocketConsumer(AsyncWebsocketConsumer):
    """
    Variant of AsyncWebsocketConsumer that automatically JSON-encodes and decodes
    messages as they come in and go out. Expects everything to be text; will
    error on binary data.
    """
	# websocket的接收消息事件只有一个,其余的什么receive、receive_json只是被调用而已,
    # 继承了某个类,有两种选择:
    	# 重写被调用的方法
        # 直接重写回调方法
    async def receive(self, text_data=None, bytes_data=None, **kwargs):
        if text_data:
            await self.receive_json(await self.decode_json(text_data), **kwargs)
        else:
            raise ValueError("No text section for incoming WebSocket frame!")

    async def receive_json(self, content, **kwargs):
        """
        Called with decoded JSON content.
        """
        pass

    async def send_json(self, content, close=False):
        """
        Encode the given content as JSON and send it to the client.
        """
        await super().send(text_data=await self.encode_json(content), close=close)

    @classmethod
    async def decode_json(cls, text_data):
        return json.loads(text_data)

    @classmethod
    async def encode_json(cls, content):
        return json.dumps(content)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值