Python 复习知识点
一. python基础篇
1. 列表(list)和元组(tuple)有什么区别?
- list和tuple都是一个可以放置任意数据类型的有序集合,都是既可以存放数字、字符串、对象等
- 列表可变,元组不可变;列表用[]标识,元组用()标识
2.Python中args,kwargs 是什么?
- 可变参数的处理(万能参数)
- args 打包成 tuple
- kwargs 被打包成 dict
3. “is”和“==”有什么区别?
- is:身份运算符,用来判断对象是否属于同一地址 (python内置函数id() 可以返回对象地址);
- ==:比较运算符,用于判断值是否相同
4.请至少列举5个 PEP8 规范(越多越好)。
- 缩进:使用4个空格的缩进,不要使用制表符(Tab键),禁止空格与Tab键混用。
- 换行:折行以确保其不会超过79个字符。这有助于小显示器用户阅读,也可以让大显示器能并排显示几个代码文件。
- 空行:使用空行分隔函数和类,以及函数内的大块代码。顶级函数间空2行,类的方法之间空1行,同一函数内的逻辑块之间空1行,文件结尾空一行。
- 注释:如果可能,注释独占一行。避免逐行添加注释,避免没有一个注释。
- 空格:运算符周围和逗号后面使用空格,但是括号里侧不加空格,如:a = f(1, 2) + g(3, 4)。
- 导入格式:每个导入独占一行,导入放在文件顶部,位于模块注释和文档字符串之后,模块全局变量和常量之前。导入应该按照从最通用到最不通用的顺序分组(标准库 -> 第三方库 -> 自定义库),每种分组中, 应该根据每个模块的完整包路径按字典序排序,忽略大小写。不要使用 from xxx import * 这种语法。
- 变量命名:尽可能的使用有意义的变量名,词能达意。下划线命名法和驼峰命名法。包名、模块名、函数名、方法、普通变量名全部使用小写,单词间用下划线连接。类名、异常名使用 首字母大写(CapWords ) 的方式, 异常名结尾加
Error
或Wraning
后缀。自定义的变量名、函数名不能和标准库中的函数名重名。 - 私有变量:小写和一个前导下划线(如:_value)。
- 内置变量:小写,两个前导下划线和两个后置下划线(如:init)。
5.并行和串行和并发的区别
串行:** 指的是一个所有的任务都按照先后顺序执行,在前一个任务没处理完的情况下是不会去处理下一个任务的,一个CPU上,按顺序完成多个任务。就像理发店只有一个理发师,每个人剪头发都需要等待前面的人处理完
**并行: ** 是指将任务分给不同的处理器去处理,每一个处理器再串行处理,比如火车站售票会有多个窗口
**并发:** 指一个处理器同时处理多个任务。一个CPU采用时间片管理方式,交替的处理多个任务。一般是是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)
6.简述 进程、线程、协程的区别 以及应用场景
线程是指进程内的一个执行单元,
# 进程
进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。
# 线程
线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度。
# 协程
协程是运行在单线程中的"并发",协程相比多线程的一大优势就是省去了多线程之间的切换开销,获得了更高的运行效率。所以可以用协程取代多线程。协程避免了无意义的调度,由此可以提高性能;但同时协程也失去了线程使用多核CPU的能力。
进程与线程的区别如果把进程比喻成项目组办公室,那么线程就是办公室里的员工,一个办公室可以有多个员工,每个员工的任务不同,但他们共享办公司资源。
(1)地址空间:线程是进程内的一个执行单位,进程内至少有一个线程,他们共享进程的地址空间,而进程有自己独立的地址空间
(2)资源拥有:进程是资源分配和拥有的单位,同一个进程内多线程共享进程的资源
(3)线程是处理器调度的基本单位,但进程不是
(4)二者均可并发执行
(5)每个独立的线程有一个程序运行的入口
协程与线程
(1)一个线程可以有多个协程,一个进程也可以有多个协程,这样Python则能使用多核CPU
(2)线程、进程都是同步机制,而协程是异步
(3)协程能保留上一次调用时的状态
7.什么是GIL锁?
Python代码的执行由Python 虚拟机(也叫解释器主循环,CPython版本)来控制,Python 在设计之初就考虑到要在解释器的主循环中,同时只有一个线程在执行,即在任意时刻,只有一个线程在解释器中运行。对Python 虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。
8.__new__和__init__的区别
-
- new__是在实例创建**之前**被调用的,因为它的任务就是创建实例然后返回该实例对象,是个静态方法。 - __init__是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值,通常用在初始化一个类实例的时候。是一个实例方法。 也就是: __new__先被调用,__init__后被调用,__new__的返回值(实例)将传递给__init__方法的第一个参数,然后__init__给这个实例设置一些参数。 1. new是构造方法,init是初始化函数。 2. new通常不需要手动定义,一般在元类编程中使用,控制类的生成过程。 3. new第一个被执行,然后执行init绑定实例变量。 4. new必须有返回值,返回值是该类的实例,它会被init函数接收,通常叫做self变量
9.Python中的实例方法、静态方法和类方法有什么区别?
- **实例方法:**接受self参数,并且与类的特定实例相关。
- **静态方法:**使用装饰器 @staticmethod,与特定实例无关,并且是自包含的(不能修改类或实例的属性)。
- **类方法:**接受cls参数,并且可以修改类本身
10.Python中的深拷贝和浅拷贝有什么区别?
- copy.copy(浅拷贝) 只拷贝父对象,不会拷贝对象的内部的子对象
- copy.deepcopy( 深拷贝) 拷贝对象及其子对象
11.Python垃圾回收机制
- 引用计数
当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少。引用计数为0时,该对象生命就结束了
- 隔代回收
将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量
- 标记-清除机制
基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放
12.什么是闭包?
指一个外包函数的内部定义的嵌套函数,而且(外包函数的)外界能够使用该函数。它通常作为返回值。
创建一个闭包必须满足以下几点:
- 必须有一个内嵌函数
- 内嵌函数必须引用外部函数中的变量
- 外部函数的返回值必须是内嵌函数
闭包的特点:
- 闭包是一个函数,而且存在于另一个函数当中
- 闭包可以访问到父级函数的变量,且该变量不会销毁
13.什么是装饰器以及写一个带参数的装饰器?
用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。装饰器的返回值也是一个函数对象 。
def mylog(type):
def decorator(func):
def infunc(*args, **kwargs):
if type=="文件":
print("文件中:日志纪录")
else:
print("控制台:日志纪录")
return func(*args, **kwargs)
return infunc
return decorator
@mylog("文件")
def fun2(a,b):
print("使用功能2",a,b)
if __name__ == '__main__':
fun2(100,200)
13.迭代器与生成器的区别?
- 生成器:
在Python中,一边循环一边计算的机制,称为生成器:generator
生成器仅仅保存了一套生成数值的算法,并且没有让这个算法现在就开始执行,而是我什么时候调它,它什么时候开始计算一个新的值,并给你返回。
- 迭代器:
1 迭代是Python最强大的功能之一,是访问集合元素的一种方式。
2 迭代器是一个可以记住遍历的位置的对象。
3 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。
4 迭代器只能往前不会后退。
5 迭代器有两个基本的方法: iter() 和 next()
14.python单引号和双引号三引号的区别?
1.单引号和双引号没有区别。都可以用就是为了方便,减少写太多的转义字符。
str='Let\'s go!' # (使用转义符 \)
str="Let's go!"
两种等价,但是第二种写法显然更优雅。
2.三个双引号用来输入多行文本,也就是说在三引号之间输入的内容将被原样保留,之中的单号和双引号不用转义,其中的不可见字符比如\n和\t都会被保留,这样的好处是你可以替换一些多行的文本。
15.python中的堆和栈
栈区:存储运行方法的形参、局部变量、返回值。由系统自动分配和回收。
堆区:new一个对象的引用或地址存储在栈区,指向该对象存储在堆区中的真实数据。
16.tcp三次握手
三次握手之所以是三次是保证client和server均让对方知道自己的接收和发送能力没问题而保证的最小次数。
第一次握手:客户端发送请求报文将SYN = 1
同步序列号和初始化序列号seq = x
发送给服务端,发送完之后客户端处于SYN_Send
状态。
第二次握手:服务端受到SYN
请求报文之后,如果同意连接,会以自己的同步序列号SYN(服务端) = 1
、初始化序列号seq = y
和确认序列号(期望下次收到的数据包)ack = x+ 1
以及确认号ACK = 1
报文作为应答,服务器为SYN_Receive
状态。
第三次握手: 客户端接收到服务端的SYN + ACK
之后,知道可以下次可以发送了下一序列的数据包了,然后发送同步序列号ack = y + 1
和数据包的序列号seq = x + 1
以及确认号ACK = 1
确认包作为应答,客户端转为established
状态。
17.一次完整的HTTP事务是怎样的一个过程?
基本流程:
a. 域名解析
b. 发起TCP的3次握手
c. 建立TCP连接后发起http请求
d. 服务器端响应http请求,浏览器得到html代码
e. 浏览器解析html代码,并请求html代码中的资源
f. 浏览器对页面进行渲染呈现给用户
18.简述yield关键字
当一个函数中出现``yield``关键字的时候,那么这个函数就是一个生成器(generator)。
函数转化为generator后,在每次调用``next``()的时候执行,遇到``yield``语句返回,再次执行时从上次返回的``yield``语句处继续执行。
19.使用__new()__方法写一个单例模式
class Single:
__obj = None
__falg = True
def __new__(cls, *args, **kwargs):
if cls.__obj = None:
cls.__obj = object.__new__(cls)
return cls.__obj
def __init__(self):
if Single.__flag:
print("__init__")
Single.__flag = False
a = Single()
b = Single()
print(a)
print(b)
20.简述with方法打开处理文件帮我我们做了什么?
打开文件在进行读写的时候可能会出现一些异常状况,如果按照常规的f.open写法,我们需要try,except,finally,做异常判断,并且文件最终不管遇到什么情况,都要执行finally f.close()关闭文件,with方法帮我们实现了finally中f.close
21.提高python运行效率的方法
1、使用生成器,因为可以节约大量内存
2、循环代码优化,避免过多重复代码的执行
3、核心模块用Cython PyPy等,提高效率
4、多进程、多线程、协程
5、多个if elif条件判断,可以把最有可能先发生的条件放到前面写,这样可以减少程序判断的次数,提高效率
22.解释什么是匿名函数,它有什么好处?
顾名思义,这类函数没有显示地定义函数名。
lambda用来表示匿名函数,可以传入多个参数,但只能有一个表达式。
好处:一次性使用,随时随地的定义更容易阅读,做了什么更是一目了然
二.数据库篇
1.什么是事务?
一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit),要么完全地执行,要么完全地不执行
2.事务应该具有4个属性
原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
持久性(Durability):一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。
3.SQL 在表中建立索引的优缺点
**优点:**为某个字段建立了索引之后,查询这个字段里面的数据的时候,效率更高,也就是快,
**缺点:**还有就是需要注意的,索引是查的效率高了,但是在表中插入或更新数据时,将有额外的操作来维护索引,所以其他的效率低了,还有占用存储空间,还有不要建立过多的索引,过多索引引起反作用!
4.数据库的优化?
- 优化索引、SQL 语句、分析慢查询;
- 设计表的时候严格根据数据库的设计范式来设计数据库;
- 使用缓存,把经常访问到的数据而且不需要经常变化的数据放在缓存中,能节约磁盘IO;
- 不采用全文索引;
- 采用更快的存储方式,例如 NoSQL存储经常访问的数据
5.什么是关联查询,有哪些?
将多个表联合起来进行查询,主要有内连接、左连接、右连接、全连接(外连接)
6.事务的四个特性是什么?
⑴ 原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。
⑵ 一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
⑶ 隔离性(Isolation)
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
⑷ 持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
7.简述数据库三大范式
# 数据库的三大特性:
'实体':表
'属性':表中的数据(字段)
'关系':表与表之间的关系
----------------------------------------------------
# 数据库设计三大范式:
1:确保每列保持原子性(即数据库表中的所有字段值是不可分解的原子值)
2:确保表中的每列都是和主键相关(表中只能保存一种数据,不可以把多种数据保存在同一张表中)--->完全属于当前表的数据
3:确保每列都和主键直接相关,而不是间接相关(在一个数据库表中保存的数据只能与主键相关)----> 消除传递依赖(间接)
比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。
# 数据库五大约束'
1.primary KEY:设置主键约束;
2.UNIQUE:设置唯一性约束,不能有重复值;
3.CHECK:检查约束
4.NOT NULL:设置非空约束,该字段不能为空;
5.FOREIGN key:设置外键约束。
三.Linux篇
1.linux中查看当前运行的进程并杀死
ps -ef |grep 进程名
kill -9 ID号
2.linux系统中profile文件介绍
是每一个用户登录时,操作系统首先执行的文件,然后再将控制权交给用户主目录下的.profile文件
Linux是一个多用户的操作系统。每个用户登录系统后,都会有一个专用的运行环境。通常每个用户默认的环境都是相同的,这个默认环境实际上就是一组环境变量的定义。用户可以对自己的运行环境进行定制,其方法就是修改相应的系统环境变量。
3.如何查看系统都开启了哪些端口?
netstat -lnp
四.web框架篇
1.列出你所知道的http状态码?
1xx:提示信息--表示请求接受,继续处理
2xx:成功表示请求成功接收,理解,接受
3xx:重定向要完成请求必须更进一步操作
4xx:客户端错误,请求有语法错误或请求无法实现
5xx:服务器端错误--服务器没有实现合法请求
2.cookie和session的区别
- session在服务器,cooking在客户端(浏览器)
- session默认存在服务器上的文件里面(也可以是内存,数据库)
session的运行依赖session_id,而session_id是存在cookie中,也就是说,若果浏览器禁用cookie,同时session也会失效(但是可以通过其他方式实现,比如在url中传入session_id)session可以放在文件,数据库,内存中都可以的 - 用户验证通常会用session
- 维持一个会话核心就是客户端的唯一标识,即session_id
3.Django的请求生命周期
用户请求 --> wsgi --> jango的中间件(方法process_request) --> url路由匹配 --> 视图 --> orm数据库操作 --> 模板渲染
--> 中间件(方法process_response) --> wsgi -->用户
1. 当用户在浏览器中输入url时浏览器会生成请求头和请求体发送给服务端请求头和请求体中会包含浏览器的动作(action)这个动作通常为get或者post提现在url之中
2. url经过Django中的wsgi再经过django的中间件,最后url到路由的映射表一条一条进行匹配一旦其中的某一条匹配成功就执行视图函数,后面的路由就不在继续匹配了
3. 视图函数根据客户端的请求查询相应的数据,返回给Django,然后Django把客户端想要的数据作为一个字符串返回给客户端
4. 客户端浏览器接受到返回的数据,经过渲染后显示给用户
4.django rest framework规范
1. url后尽量用名词,因为rest frame是面向资源的编程,因此url命名时能体现出资源
2. method的不同,实现增删改查的操作
3. 版本号,因为有版本的更替,为了体现出版本的过度,因此在发请求的时候,要体现出版本号
4. 返回值,与以往只返回json不同,rest api规范要加上状态码。
5. 域名,由于前后端分离,因此要处理跨域问题,解决方法:jsonp,cors
6. 过滤,通过url传参的形式传递搜索条件(列如:指定返回的记录数量,指定分页等)
5.django、flask框架的比较?
- django,大而全的框架,它的内部组件比较多,内部提供:ORM、Admin、中间件、Form、ModelForm、Session、缓存、信号、CSRF;功能也相当完善。
- flask,微型框架,内部组件就比较少了,但是有很多第三方组件来扩展它,定制化程度高。 比如说有那个wtform(与django的modelform类似,表单验证)、flask-sqlalchemy(操作数据库的)、flask-session、flask-migrate、flask-script、blinker可扩展强,第三方组件丰富。所以对他本身来说有那种短小精悍的感觉
django和flask的共同点就是,他们2个框架都没有写socket,所以他们都是利用第三方模块wsgi。
但是内部使用的wsgi也是有些不同的:django本身运行起来使用wsgiref,而flask使用werkzeug wsgi
还有一个区别就是他们的请求管理不太一样:django是通过将请求封装成request对象,再通过参数传递,而flask是通过上下文管理机制。
6.什么是wsgi?
是web服务网关接口,是一套协议。
是通过以下模块实现了wsgi协议:
- wsgiref
- werkzurg
- uwsgi 关于部署
以上模块本质:编写socket服务端,用于监听请求,当有请求到来,则将请求数据进行封装,然后交给web框架处理。
7.列举django的内置组件?
表单form:
- 对用户请求的数据进行校验
- 生成HTML标签
PS:
- form对象是一个可迭代对象。
- 问题:如何实现choice的数据实时更新?(动态数据,而不是写死)
- 解决:给该字段定义成ModelChoiceField的时候利用好"queryset"参数
class UserForm(Form):
ut_id = ModelChoiceField(queryset=models.UserType.objects.all()) # 从另一张依赖表中提取数据
依赖表:
class UserType(models.Model):
title = models.CharField(max_length=32)
信号signal:
django的信号其实就是django内部为开发者预留的一些自定制功能的钩子。
只要在某个信号中注册了函数,那么django内部执行的过程中就会自动触发注册在信号中的函数。
如:
- pre_save & post_save 在ORM模型的save()方法调用之前或之后发送信号
- pre_delete & post_delete 在ORM模型或查询集的delete()方法调用之前或之后发送信号
- request_started & request_finished 当接收和关闭HTTP请求时发送信号
- m2m_changed 当多对多字段被修改时发送信号
场景:
在数据库某些表中添加数据时,可以进行日志记录。
中间件middleware:
对所有的【请求】进行【批量】处理,说得直白一点中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作,它本质上就是一个自定义类。其影响的是全局,需谨慎使用。应用:用户登录校验问题:为甚么不使用装饰器?如果不使用中间件,就需要给每个视图函数添加装饰器,太繁琐。
权限:
用户登录后,将权限放到session中,然后再每次请求进来在中间件里,根据当前的url去session中匹配,判断当前用户是否有权限访问当前url,有权限就继续访问,没有就返回,
检查的东西就可以放到中间件中进行统一处理,在process_request方法里面做的,
我们的中间件是放在session后面,因为中间件需要到session里面取数据。
会话session:
cookie与session区别
(a)cookie是保存在浏览器端的键值对,而session是保存的服务器端的键值对,但是依赖cookie。(也可以不依赖cookie,可以放在url,或请求头但是cookie比较方便)
(b)以登录为例,cookie为通过登录成功后,设置明文的键值对,并将键值对发送客户端存,明文信息可能存在泄漏,不安全; session则是生成随机字符串,发给用户,并写到浏览器的cookie中,同时服务器自己也会保存一份。
(c)在登录验证时,cookie:根据浏览器发送请求时附带的cookie的键值对进行判断,如果存在,则验证通过; session:在请求用户的cookie中获取随机字符串,根据随机字符串在session中获取其对应的值进行验证
跨域请求cors(场景:前后端分离时,本地测试开发时使用):
如果网站之间存在跨域,域名不同,端口不同会导致出现跨域,但凡出现跨域,浏览器就会出现同源策略的限制。
解决:在我们的服务端给我们响应数据,加上响应头 --> 在中间件加的。
缓存cache:
常用的数据放在缓存里面,就不用走视图函数,请求进来通过所有的process_request,会到缓存里面查数据,有就直接拿,没有就走视图函数。
关键点:1:执行完所有的process_request才去缓存取数据
2:执行完所有的process_response才将数据放到缓存
关于缓存问题
1:为什么放在最后一个process_request才去缓存?
因为需要验证完用户的请求,才能返回数据
2:什么时候将数据放到缓存中?
第一次走中间件,缓存没有数据,会走视图函数,取数据库里面取数据,
当走完process_response,才将数据放到缓存里,因为,走process_response的时候可能给我们的响应加处理。
3:为什么使用缓存?
将常用且不太频繁修改的数据放入缓存。
以后用户再来访问,先去缓存查看是否存在,如果有就返回
否则,去数据库中获取并返回给用户(再加入到缓存,以便下次访问)
CSRF-TOKEN:
目标:防止用户直接向服务端发起POST请求。
对所有的post请求做验证,将jango生成的一串字符串发送给后台,一种是从请求体发过来,一种是放在隐藏的标签里面。
方案:先发送GET请求时,将token保存到:cookie、Form表单中(隐藏的input标签),
以后再发送请求时只要携带过来即可。
8.列举django中间件的5个方法?以及django中间件的应用场景?
# 这些方法中的参数都是与视图函数参数对应的process_request(self, request) 主要方法。请求刚进来时,执行视图函数之前调用。(无return)
process_view(self, request, callback, callback_args, callback_kwargs) URL路由匹配成功后,执行视图函数之前调用,拿到视图函数对象,及其所有参数。(无return)
process_exception(self, request, exception) 执行视图函数中遇到异常时调用。(无return)
process_template_response(self, request, response) 很少用。执行了render()渲染方法后调用。(有return)
process_response(self, request, response) 主要方法。执行视图函数结束之后有响应时调用。(有return)
9.F和Q表达式的作用?
F:主要用来对字段的值进行四则计算。
Goods.objects.update(price=F("price")+10) # 对于goods表中每件商品的价格都在原价格的基础上增加10元
Q:用来进行复杂查询,实现"与"、"或"、"非"查询。
Q(条件1) | Q(条件2) # 或
Q(条件1) & Q(条件2) # 且
~ Q(条件) # 非
10.谈谈你对Restfull规范的认识?
Restful其实就是一套编写接口的'风格规范',规定如何编写以及如何设置返回值、状态码等信息。
最显著的特点:
# 用Restful:
给用户一个url,再根据不同的method在后端做不同的处理
比如:post创建数据、get获取数据、put和patch修改数据、delete删除数据。
# 不用Restful:
给调用者很多url,每个url代表一个功能,比如:add_user/delte_user/edit_user/
# 当然,还有其他的,比如:
'版本' 来控制让程序有多个版本共存的情况,版本可以放在 url、请求头(accept/自定义)、GET参数
'状态码' 200/300/400/500
'url中尽量使用名词' restful也可以称为“面向资源编程”
'api标示'
api.luffycity.com
www.luffycity.com/api/
11.为什么要使用Django Rest Framework框架?
# 在编写接口时可以不使用django rest framework框。
# 不使用:也可以做,可以用django的CBV来实现,开发者编写的代码会更多一些。
# 使用:内部帮助我们提供了很多方便的组件,我们通过配置就可以完成相应操作,如:
'序列化'可以做用户请求数据校验+queryset对象的序列化称为json
'解析器'获取用户请求数据request.data,会自动根据content-type请求头的不能对数据进行解析
'分页'将从数据库获取到的数据在页面进行分页显示
#还有其他组件:'认证'、'权限'、'访问频率控制'
12.简述Flask上下文管理流程?
# a、简单来说,falsk上下文管理可以分为三个阶段:
1、'请求进来时':将请求相关的数据放入上下问管理中
2、'在视图函数中':要去上下文管理中取值
3、'请求响应':要将上下文管理中的数据清除
# b、详细点来说:
1、'请求刚进来':
将request,session封装在RequestContext类中
app,g封装在AppContext类中
并通过LocalStack将requestcontext和appcontext放入Local类中
2、'视图函数中':
通过localproxy--->偏函数--->localstack--->local取值
3、'请求响应时':
先执行save.session()再各自执行pop(),将local中的数据清除
13.Flask中的g的作用?
# g是贯穿于一次请求的全局变量,当请求进来将g和current_app封装为一个APPContext类;
# 再通过LocalStack将Appcontext放入Local中,取值时通过偏函数在LocalStack、local中取值;
# 响应时将local中的g数据删除;
14.ORM的实现原理?
# ORM的实现基于一下三点
映射类:描述数据库表结构,
映射文件:指定数据库表和映射类之间的关系
数据库配置文件:指定与数据库连接时需要的连接信息(数据库、登录用户名、密码or连接字符串)
细点来说:
1、‘请求刚进来’:
将request,session封装在RequestContext类中
app,g封装在AppContext类中
并通过LocalStack将requestcontext和appcontext放入Local类中
2、‘视图函数中’:
通过localproxy—>偏函数—>localstack—>local取值
3、‘请求响应时’:
先执行save.session()再各自执行pop(),将local中的数据清除