面试旁白

发布时间 2023-04-25 23:07:25作者: 性格如此w

面试旁白

内置函数

sum()、sorted()、open()、float()、range()、print()、set()无序不重复元素集、getattr\setattr\hasattr

匿名函数

lambda 没有名字的函数 需要运用在一个函数上,只要用一次,又不想费神去命名,有局限性。只能用一次,也无法在其他类中使用。但是在日常的使用过程中,lambda主要以参数的用法存在的。。可以用在比较大小、排序、过滤、映射配合着使用

递归函数

函数直接或者间接的调用函数本身,则称为递归函数。如果在一个函数内部,调用本身自身,那么这个函数就是递归函数

特性

  1. 必须有一个明确的结束条件
  2. 每进入更深一层的递归时,问题规模要比上一次递归都应减少

优点:逻辑简单清晰,缺点是过深的递归容易导致栈溢出

尾递归:为了解决递归调用栈溢出的问题。尾递归是指,在函数返回的时候,调用自身,并且 return 语句中不能包含表达式

尾递归和循环的效果一样,可以把循环看成一种特殊的尾递归函数。但是python没有针对尾递归做优化,Python解释器也没有做优化,所以还是要注意递归深度

装饰器

装饰器通常情况下本质是闭包,在不改变被装饰的函数的源代码和调用方式的情况下给对象新增新的功能或者方法。

被装饰的函数会被当做参数传入装饰器,最后再返回

应用场景:

  1. 权限的校验:django中的@login_required和@permission_required装饰器
  2. 性能测试:计算函数运行时间,运行次数,
  3. 插入日志

有了装饰器,我们就可以抽离出大量与函数功能本身无关的代码,增加一个函数的重用性和整体代码的可读性

反射机制

反射机制使得程序在运行的过程中动态修改结构和行为的能力,通过字符串的形式去对象中操作(增删查改)

python中主要有4个重要的内置函数:

getattr

判断类、对象或者模块是否有相应的功能或者方法,
getattr(obj,str,default=None)
# 判断obj中是否有str属性,有就返回,没有的时候如果有第三个参数就返回,没有就报错

setattr

设置属性。第三参数为新的属性值

hasattr

判断是否有某个属性,有就返回True,没有就返回False

delattr

删除某个属性

oop编程

面向对象的本质,其实就是一种如何将大量的代码和数据进行管理的归档方法。每一个类,其实就像一个文档盒子,把相似的东西,可以归类在同一个盒子里

魔法方法

init__和__new

iter__和__next

str:执行打印的时候自动触发

getattr(self,name):当对象获取一个不存在的属性时的行为,

call 类创建出一个对象,对象加括号的时候自动触发

io多路复用

io多路复用是一种同步io模型,实现一个线程可以监听多个文件句柄,一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作

进程池

进程池是资源进程、管理进程组成的技术的应用。

进程池技术的应用由以下两部分组成:

资源进程

预先创建好的空闲进程,管理进程会把工作分发到空闲进程来处理

管理进程

管理进程负责创建资源进程,把工作交给空闲资源进程处理,回收空闲资源进程

管理进程要有效的管理资源进程,那么管理进程跟资源进程间必然需要交互,通过IPC,信号,信号量消息队列,管道等进行交互。(先别说)

生产消费者模型

生产者

产生数据的模块,就形象地称为生产者;

消费者

处理数据地模块,就成为消费者

缓冲区(阻塞队列)

生产者和消费者之间的中介叫做缓冲区

生产消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题,生产者和消费者彼此之间不能直接通讯,二通过阻塞队列来进行通信

生产者生产完数据不用等待消费者处理,而是直接丢给阻塞队列,消费者不找生产者要数据,而是直接去阻塞队列中直接取,阻塞队列相当于一个缓冲区,平衡了生产者和消费者的处理能力。这个阻塞队列就是给生产者和消费者解耦合的

Django的过滤与排序

排序

排序功能接口只针对于:获取所有数据,也就是list方法接口,并且需要视图类继承GenericAPIView及其子类

视图类

from rest_framework.generics import ListAPIView
from rest_framework.filters import OrderingFilter
from .models import Book
from .serializer import BookSerializer

class BookView(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 重写GenericAPIView提供的属性,把排序类加进去
    filter_backends = [OrderingFilter, ]
    # 需要排序的字段,不写默认为序列化类所有字段
    ordering_fields = ['price']
    
    def get(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)

根据访问地址中带参数来排序

按照price字段来排序

http://127.0.0.1:8000/books?ordering=price  # 升序
http://127.0.0.1:8000/books?ordering=-price   # 降序
http://127.0.0.1:8000/books?ordering=字段1,字段2

过滤

过滤用于筛选数据,与排序一样,只作用于list方法的接口,并且视图类要继承GenericAPIView类及其子类。

排序过滤的原理

关键在于GenericAPIView类中的filter_queryset方法

内置过滤类

SearchFilter过滤类:用于模糊查询

# SearchFilter过滤类 模糊查询
from rest_framework.generics import ListAPIView
from rest_framework.filters import SearchFilter
from .models import Book
from .serializer import BookSerializer

class BookView(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 重写GenericAPIView提供的属性,把过滤类加进去
    filter_backends = [SearchFilter, ]
    # 需要过滤的字段,不写就无法过滤
    search_fields = ['name', 'price']

    def get(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)

过滤:

http://127.0.0.1:8000/books?search=5

# 根据search_fields过滤数据,search=5相当于:
  
name like 5 or price like 5   
第三方过滤类

安装:

pip install django-filter

视图类使用:

from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.generics import ListAPIView
from .models import Book
from .serializer import BookSerializer

class BookView(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 重写GenericAPIView提供的属性,把过滤类加进去
    filter_backends = [DjangoFilterBackend, ]
    # 需要过滤的字段
    filter_fields = ['name','price']
    
    def get(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)

根据访问地址中带参数来过滤

过滤:

http://127.0.0.1:8000/books?name=xx&price=5
        
相当于:
    
name=xx and price=5
自定义过滤类
from rest_framework.filters import BaseFilterBackend
# 继承BaseFilterBackend
class BookFilter(BaseFilterBackend):
    # 重写filter_queryset
    def filter_queryset(self, request, queryset, view):
        """主要操作queryset参数"""
        # 返回的数据就是过滤后的数据
        return queryset.filter(price__gt=50)

视图类:

from rest_framework.generics import ListAPIView
from .models import Book
from .serializer import BookSerializer
# 导入过滤类
from .throttling import BookFilter
class BookView(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 重写GenericAPIView提供的属性,把过滤类加进去
    filter_backends = [BookFilter, ]

    def get(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)

restful规范

Restful是一种定义Web APl接口的设计风格,尤其适用于前后端分离的应用新模式

十个规范

  1. 数据的安全规范,通常使用https协议
  2. 接口中带有api标识
  3. 多版本共存,路由中带版本信息
  4. 数据就是资源,尽量使用名词,
  5. 资源操作由请求方式决定(method)
  6. 请求地址带过滤条件
  7. 响应状态码
  8. 返回数据中带错误信息
  9. 返回的结果应该符合规范
  10. 返回数据中带链接
1.数据的安全规范,通常使用Https(http+ssl)协议
	url连接一般采用https协议进行传输
    采用https协议,可以提高数据交互过程中的安全性
   
2. 接口中带api标识
	可以写在域名中,也可以写在路由中(我一般都写在路由中)
    
3. 多版本共存,路径中带版本信息

4. 数据即是资源,均使用名词,尽量不出现动词(最核心的部分)

5. 资源操作由请求方式决定(method)
	-操作资源一般涉及到增删改查
        https://api.baidu.com/books    - get请求:获取所有书(获取所有)
        https://api.baidu.com/books/1  - get请求:获取主键为1的书(获取一条)
        https://api.baidu.com/books    - post请求:新增一本书书(新增一条)
        https://api.baidu.com/books/1  - put请求:修改主键为1的书(整体修改一条)
        https://api.baidu.com/books/1  - patch请求:修改主键为1的书(局部修改一条)
        'ps:patch用的不多,一般用put即可'
        https://api.baidu.com/books/1  - delete请求:删除主键为1的书(删除一条)
 
6. 在请求地址中带过滤条件
 	指定返回记录的数量
    指定返回记录的开始位置
    指定第几页,以及每页的记录数
    指定返回结果按照哪个属性排序,以及排序顺序
    指定筛选条件
  
7. 响应状态码:
    1xx: 请求正在处理
    2xx:成功响应
    3xx:重定向
    4xx:客户端错误
    5xx: 服务端错误
     '常见的需要记住'
    	响应状态码2XX		200:常规请求		201:创建成功
	 	响应状态码3XX		301:永久重定向	302:暂时重定向
	 	响应状态码4XX		403:请求无权限	404:请求路径不存在	405:请求方法不存在
	 	响应状态码5XX		500:服务器异常
          
 8. 返回数据中带错误信息
	{
        code:0
        msg:"ok/用户名错误"
    }
 
9. 返回的结果应该符合规范:
    GET 获取所有数据,返回资源对象的列表
    GET 单个对象,返回单个资源对象
    POST 新增对象, 返回新生成的资源对象 
    PUT 修改对象: 返回完整的资源对象
    DElETE 删除: 放回一个空文档
       
 
10. 响应数据中带链接
	 响应数据要带有状态码,状态信息以及数据本身

django的生命周期请求流程

JWT的认证与签发

概念:

在用户注册或者登陆后,我们想要记住用户的登录状态,或者为用户创建身份认证的凭证,就是用Json Web Token(本质就是token)认证机制

构成和原理

JWT就是一段字符串,由三段信息构成

# 第一部分: 头部 header
  -主要有两部分信息:  声明这是jwt
        声明加密算法 通常直接使用 HMAC SHA256
    然后加头部进行base64加密(该加密是可以对称解密的),构成了第一部分
# 第二部分: 荷载 payload
    -荷载就是存放有效信息的地方,像是承载的货品,主要包含三个部分:
    1.标准中的注册声明
    2.公共的声明
    3.私有的声明
    # 荷载: payload
    	-存放有效信息的地方
        - 过期时间
        - 签发时间   -用户id  -用户名字等
    
# 第三部分: 签证信息,签证信息由三部分组成:
	header(base64加密后的)
    payload(base64加密后的)
    secert
 
这个部分需要base64加密后的header和base64加密后的payload使用 .  连接组成的字符串,然后通过header中声明的加密方式进行 加盐secret组合加密,然后构成jwt的第三部分。

将这个三个部分用.连接成完整的一个字符串,构成了最终的jwt

本质原理

jwt认证算法:签发与校验

签发: 根据登录提交来的 账号+密码+设备信息 签发token

校验: 根据用户端带token的请求 反解出 user 对象

drf项目的jwt认证开发流程(重点)

  1. 用账号密码访问登录接口,登录接口逻辑中调用 签发token算法,得到token,返回给客户端,客户端自己存到cookies中
  2. 校验token的算法应该写在认证类中(在认证类中调用),全局配置给认证组件,所有视图类请求,都会进行认证校验,所以请求带了token,就会反解出user对象,在视图类中用request.user就能访问登录的用户

注意:登录接口需要做 认证 +权限 两个局部禁用

base64 应用场景
'''
1 jwt 使用了base64
2 网络中传输数据,也会经常使用 base64编码
3 网络传输中,有的图片使用base64编码
'''
s='去网上找,比如12306的图片都是用base64加密过的,找到他的地址去掉前面两部分就能得到base64加密后的字符串'
res=base64.b64decode(s)
with open('a.png','wb') as f:
    f.write(res)

xadmin替换

内置功能丰富:Xadmin作为一款全面的后台管理系统框架,不仅提供了基本的CRUD功能,还内置了丰富的插件功能。包括数据导出、书签、图表、数据添加向导及图片相册等多种扩展功能。

action装饰器

1.视图类中的方法,会用到一些其他的名字,必须要使用action装饰器做映射

2.action中的一些参数:

  • methods: 请求方式,列表
  • detail: pk有关,默认是False, 控制生成的路由是:/user/login还是/user/pk/login
  • url_path: 控制生成的/user/后面的路径是什么,如果不写,默认就是方法名
  • url_name: 别名,用于反向解析
@action(methods=['POST',],detail=False, url_path='login')
def login(self,request):