答:Django的中间件就是一个类,是介于请求和响应之间的一道处理过程,相对比较轻量级,并且在全局上改变Django的输入和输出。
2、中间价的几个方法?
答:中间件一共有五个方法
process_request(self,request)
process_view(self,request,callback,callback_args,callback_kwargs)
process_template_response(self,request,response)
process_exception(self,request,exception)
process_response(self,request,response)
3、中间件的执行流程?
当用户请求的时候会依次经过所有的中间件,这个时候请求的是所有process_request,当最后一个process_request到达路由关系映射之后,返回到中间件的response_view,到达视图函数中,视图函数处理后,如果有模板渲染,执行process_template_response,如果在以上执行的过程中出错了,执行process_exception,最后通过process_response返回给请求者。如下图所示
注意:
1、process_request一般不要有返回值,如果有返回值后续视图函数就不会执行了,会执行自己的response和process_response;process_response中必须要有返回值。
2、process_view如果有返回值,会越过其他process_view,但是所有的process_response还是会执行
4、中间件的应用?
当批量做一些操作的时候可以使用中间件
当有几个函数要做批量处理的时候可以使用装饰器的方法
比如:
权限
CORS跨域(由于好多的请求都可能存在跨域问题,所以直接写一个中间件,就不用每次都在响应的时候设置响应头了)
csrf(执行process_view,在这view里面去拿csrf_token,在看有没有加特别的装饰器,特殊的装饰器,如果那个函数不需要认证,则可以取设置一个特殊的装饰器)
session
缓存(请求进来,先去缓存获取,再往后执行)
从总体来说分为以下几个过程:
1、输入网址按enter建
3、浏览器向服务器发送TCP连接,与浏览器建立tcp三次握手
4、握手成功后,浏览器向服务器发送HTTP请求,请求数据包。
5、服务器处理收到的请求,将数据返回到浏览器,
7、连接结束
三次握手的流程:
答:请求一进来会先走wsgi(wsgiref和uwsgi),到达中间件-----路由----视图-----从数据库获取数据进行模板渲染。
一旦匹配成功则不再继续
若要从url中获取一个值,只需要在他周围放置一对圆括号。
1、有名分组和无名分组
在Python正则表达式中,命名正则表达式组的语法是(P
分发include
如果url出现覆盖现象的情况下,匹配第一个url
2、反向解析(不让url硬编码)
答:有两种方式
在视图中,通过reverse反向解析,还可以加一个namespace的参数。Namespace:name
reverse('n1')
reverse('n2',args=(666,))
在模板中
{%url'n1'%}{%url'n2'666%}
3、在源码里面看到路由还可以以这样的方式返回([],None,namespace)。Stark组件就是这样实现的
Request.method#请求方法
Request.GET#GET请求
Request.POST#POST请求
Request.path#获取url路径,不包括参数
Request.get_full_path#获取url路径,包括参数
Request.cookies
Request.FILEs
Request.user
Request.session
1、什么是ORM
答:ORM是对象关系映射
数据库中的表名对应-------类名
字段------------------------属性
表记录-------------------------类实例化对象
ORM的两大功能
操作表
操作数据行
2、谈谈你对QuerySet的理解,以及它有哪些方法?
答:Queryset可切片,可迭代,缓存机制、惰性查询(不用不求)
Update,create,delete
基于对象的查询
all,filter,get,exclude,values,values_list,order_by,reverse,distanct,count,first,last,exits,only,defer
all:打印的是一个QuerySet集合,一个列表里面放的对象
values:是一个字典的形式
values_list:是一个元组的形式
基于双下划线的查询
Id__in
Id__lt#小于
Id__gt#大于
Name__contains#包括。。。
Name__icontains#包括。。。但是大小写不敏感
Id__range()#范围是在。。。betweenand
Startswith,isstartwith,endswith,iendswith
3、render函数的功能?
返回一个页面
模板语法:将变量如何巧妙的嵌入到HTML页面中
Redirect:发送了第二次请求,url更新
Render:只会返回页面内容,但是未发送第二次请求
将变量如何巧妙的嵌入到HTML页面中
3、模板语法之标签{%tag%}
创建的有
for标签
for….empty(给出的组是空的或者没有找到时,可有所操作)
if标签
{%csrf_token%}+
4、模板语法之过滤器{{obj|filter_name:param}}
a)Defaule:如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。
b){{value|length}}:返回值的长度。它对字符串和列表都起作用
c){{value|filesizeformat}}:将值格式化成我们人能看懂的文件尺寸
e){{value|slice:”2:-1”}}:切片
f){{safe}}:确保你的数据是安全的,才被当做标签
1….Form组件可以做几件事情?
a)用户请求数据验证
b)自动生成错误信息
c)打包用户提交的正确信息
d)保留上次输入内容
e)自动创建input标签并且可以设置样式
2、Form组件的使用
写一个类
字段(参数)
-require
-max_length
-min_length
-error_message
-validate=[]#自定制的正则表达式
方法
-clean_字段名称
使用:
-GET请求实例化直接render回去
POST
实例化(request.POST)
is_valid()
clean_data
errors
注意:ChoiceField数据源时时更新
9、Ajax的特点:
异步交互:当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!
局部刷新:整个过程中页面没有刷新,只是刷新页面中的局部位置而已!
9、csrf跨站请求的三种方式?
1、自己组装一组键值对发过去
2、自己设置头信息
3、$.ajaxSetup({10、怎么上传文件?
有两种方式:
1、Form表单上传文件。需要加一个enctype=’multipart/form-data’
2、Ajax上传文件
利用FormData,既可以处理二进制,也可以处理字典,列表等
ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件.
要是使用FormData一定要加上:
一定要加上:
contentType:falseprocessDate:false#不做预处理
1、为什么学Python?是什么时候开始接触Python的?15年接触Python
答:公司项目用Python
容易上手
Python火
(2)学校社团有学习Python的,我那时候感兴趣,就报名了。在那里面成长了不少,一个组一个组的分配学习任务,每天一块讨论问题,学着学着感觉python语言比起java的语言简练了,就慢慢的自学、通过看网上的视频,看官方文档等。
答
a、代码编排:缩进,4和空格的缩进;换行可以使用反斜杠
b、文档排版:不要在一句import中导入多个类,比如importos,sys不推荐这样。
c、空格的使用:函数的左右括号前不要加空格,操作符左右各加一个空格;if/for/whilt语句中,即使执行语句只有一句,也另起一行写
d、注释:行注释:用#块注释:用’’’’’’
e、文档描述:一个功能写完可以写一个描述,让人一看就知道是干啥的
f、命名规范:命名的时候避免使用关键字命名;首字母不能是数字开头,可以是字母数字下划线的组合;尽量命名的时候有功能性的命名。
答:函数是编程是使用一系列的函数去接解决问题,会根据参数的不同产出不同的结果。除了匿名函数外,Python还是用filter,map,reduce函数来支持函数式编程
匿名函数:也就是lambda表达是,当一些简单的功能需要用函数去处理的时候就可以使用匿名函数
filter():包括两个参数,分别是function和list。根据function中返回值是否为True来过滤list参数中的项,最后返回结果。
map():两个参数,一个是函数名,一个是列表。将函数里面的处理结果以列表的形式返回
reduce():具体的做法如下:首先从序列中去除头两个元素并把它传递到那个二元函数中去,求出一个值,再把这个加到序列中循环求下一个值,直到最后一个值。
reduce(lambdax,y:sum([x,y]),range(1,101))#吧1传给了x,吧101传给了y,计算除了1-100的和
答:匿名函数,也就是lambda表达式,一些简单的功能需要用函数处理的时候可以使用匿名函数
匿名函数顾名思义就是函数没有名字,因此不用担心函数名冲突,
不过python对匿名函数的支持有限,只有一些简单的情况下可以使用匿名函数。
答:使用with后不管with中的代码出现什么错误,都会进行对当前的对象进行清理工作
原理:
上下文管理器就是在对象内部实现了两个方法:__enter__和__exit__()
__enter__方法会在with代码块执行之前执行
__exit__方法会在代码块执行结束后执行
在不修改源代码的基础上,在函数执行之前或者执行之后添加的操作
Python的作用域简单的说也就是作用范围,
作用域分为两种:
全局作用域:在整个文件的任意位置都能被引用,全局有效(全局命名空间与内置命名空间的名字都属于全局范围)
局部作用域:局部命名空间,只能在局部范围内生效
Python搜索变量的顺序?
LEGB
首先找函数内部local,然后找函数内部的函数enclosing,其次找全局global,最后build-in找内置作用域。
为什么要有作用域?
为了函数内部的变量不影响到全局
答:内部的函数包含了对函数作用域中变量的引用而非全局作用域
判断是否是闭包的方法?__closure__
答:strip(),split(),startwiths(),index(),endwiths(),replace,join,format,capitalize(首字母大写),upper(),Lower()
Index和find的区别?
Index找索引,找不到就会报错,
Find找索引,找不到返回-1
增:append:添加一个元素到末尾,只能添加一个元素。可以添加一个列表
extend:添加多个元素
insert(3,’age’):按照索引添加一个元素
删:remove,pop.,clear,del
Remove和pop的区别?
Remove(‘b’)#指定一个元素删除,如果元素不存在则报错,没有返回值
Pop()#根据索引删除一个元素,如果不传索引,默认从末尾删除一个值,有返回值
Clear直接删除列表中的所有元素
Del可以根据切片删除多个值
改:a[4]=‘sdsdf’根据索引修改
查:a[3]索引查看元素
a.index(‘a’)查看一个元素的索引
a.count(‘a’)查看a这个元素在这个列表中出现的次数
切片
a[1:3]注意顾头不顾尾
例题:a=["q","w","e","r","t","y"]
请通过切片打印出:['r','e']答:a[3:1:-1]
Get,pop,update,copy,items,popitems.values,keys,等
Count,index
12、集合常见方法?
add,clear,copy.,
|并集(print(pythons.union(linuxs)))
&交集(print(pythons.intersection(linuxs)))
-差集(print(pythons.difference(linuxs)))
^对称差集(print(pythons.symmetric_difference(linuxs)))
集合的元素遵循三个原则:
1、每个元素都是不可变数据类型的
2、没有重复的元素
3、无序
a)有序字典
b)命名元组
c)默认值字典
d)双向队列dequeue
unicode:优点是字符转换数字的时候速度快,缺点是占用空间大
utf-8:优点是精准,可变长,转换速度慢,缺点是节省空间
【unicode:多的字符都是2bytes,优点是字符转换数字的时候速度快,缺点是占用空间大】
【utf-8:精准,可变长,优点是节省空间;缺点是转换速度慢,因为每次转换都需要计算出需要多长bytes才能准确表示】
答:我接触的他们的最大的区别是编码的不同
(1)Python2里面默认是ascII,python2中的字符串就是bytes,python2中的字符串前面加u,就是unicode
Python3里面默认的是unicode,python3中的字符串被识别为unicode,python3中的字符串encede得到bytes
(2)python2中的字符串有str和unicode两种类型
Python3中的字符串有str和bytes两种类型
(3)Xrange()返回的是一个可迭代对象和range()返回的是一个列表
(4)Python2中的文件读取Xreadlines和Python3中的readline、
Python采用的是引用计数为主,标记-清除机制和分代计数两种机制为辅
引用计数:
Python中万物皆对象,他们的核心就是一个结构体:pyObject
当一个对象有新的引用时,他的引用计数就会增加,当一个对象被删除,他的引用计数就会减少。
当引用计数为0时,该对象的生命就结束了。
引用计数机制的优点:
1、简单
2、实时性:一旦没有引用,内存就直接释放了,不用像其他机制等到特定的时机
应用计数机制的缺点:
1、维护引用计数消耗资源
2、循环引用
标记-清除机制
基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发
遍历以对象为节点、以引用为边构成的图,吧所有可以访问到打上标记,然后清扫一遍内存空间,
吧所有没标记的对象释放。
分代技术
答:多道技术也就是多个程序
a)什么时候要切?
ii.当CPU遇到IO阻塞的时候要切
2、空间上的复用:内存要支持同时跑进多个程序
a)为应用程序提供如何使用硬件资源的抽象
b)把多个程序对硬件的竞争变得有序化(管理应用程序)
答:从写代码的角度来说,
函数式编程是:将公共功能编写成一个函数,通过参数的不同来产出不同的结果
面向对象编程是:主要体现在三大特性:封装、继承、多态
多态:鸭子类型(只要能呱呱叫就是鸭子了),由于Python是非强类型的,例如传入的值不管是什么,只要有我自己想调用的方法就行了,本身就是多态的。
封装:
数据的封装
举例、:在构造方法里面self.name,self.age
方法和属性的封装:
举例:像是动物类,狗类,猫类等
继承:如果好多类有相同的方法和属性,为了减少代码的重用,就可以提取到基类中
在Python中是有多继承的,当前类中没有方法或者其他字段,去基类中查找。
派生类:谁继承谁就是派生类,也就是子类
广度优先:新式类
深度优先:经典类
经典类:在Python2中的继承没有继承object类的是经典类
新式类:在Python2中继承了object的是新式类
哦,还有一些比如特殊的带双下划线的方法和metaclass,后面研究了一下
特殊的方法有哪些呢?
__call__:单利用metaclass创建类的时候;用类做装饰器;Flask源码;restframework做自定义验证规则的时候
__new__:单利模式;自定义Form验证;wtforms源码;Djangorest-framework中,序列化源码(实例化的时候,先执行__new__,再执行__init__)****;
__init__:构造方法
__del__析构方法,当对象在内存中被释放时,自动触发执行。析构函数的调用都是由解释器在进行垃圾回收时自动触发代码的执行
__iter__:一个对象for循环的时候,返回一个迭代器,生成器也是一个迭代器。stark组件中组合搜索的时候用到过*****
__getattr__:Flask源码,自定义本地线程的时候用过;djangorestframe中request中取值
__setattr__:
__getitem__:session源码fun[‘qqq’]
__next__:
__dict__:取到类中的所有方法和属性。自定义Form组件的时候用到过
__add__:对象相加默认会执行__add__方法
data=obj1+obj2
#obj1.__add__(obj2)
减,成
__class__
__enter__
__exit__
__str__:改变对象的字符串显示
metaclass
-流程:先执行元类的__init__方法
如果实例化一个对象先执行__call__方法
完了执行自己类的__new__方法和__init__方法
-wtforms源码
如果我们没有对异常进行任何预防,那么在程序执行过程中就会发生异常,就会终端程序,不会
继续执行后续代码,所以我们调用Python默认的异常处理器来捕捉异常。
异常处理的机制
其实通过if也是可以处理异常的,只不过如果逻辑特别多的时候,都使用if去处理异常,会使代码的可读性极差。所以还有一种机制
try….except…else….finally
try里面放的是被检测的代码块,except是try中一旦检测到异常,就执行except里面的代码,
else:如果出现问题了不会执行else里面的代码,如果都正确了就会执行else里面的代码。
Finally:不管这段代码有没有出错,都会执行的内容
Assert……断言:判断assert后面紧跟的语句是True还是False。如果是True则继续执行后续代码,如果是False就会报错,
ZeroDivisionError除数为0
SyntaxError语法错误
IndexError索引超出了范围
KeyError请求一个不存在的字典关键字
IOError输入输出错误,比如你要读的文件不存在
AttributeError尝试访问未知的对象属性
ValueError传给函数的参数值类型不正确
Python2中有两种:
经典类:不继承object
新式类:继承object
多继承的时候查找顺序是不同的
经典类:深度优先
新式类:广度优先
Python3中只有新式类,,可以用__mro__方法查看类继承的顺序
Django的CBV模式
Restframework
中间件
__init__:初始化一个类实例,第一个参数是self
__iter__
__new__:在__init__执行之前,__new__方法是新建一个类实例,第一个参数是cls
__call__:哪里用过,在restframework序列化在用户请求数据验证时,自定义验证规则、Django的请求入口:__call__方法
Flask请求入口:也是执行__call__方法
Django中间件执行的__call__方法,在__call__方法里面process_request,….
__setitem__:自定义session的时候用了。设置类成员
__dict__
Type创建类,metaclass不写默认是由type创建的类
g)@propery就是吧一个方法当做一个属性来用
h)访问类或示例的属性是直接通过obj.xxx的形式访问,但property是一个特殊的属性,访问
添加了装饰器@property的方法无序额外的添加()来调用,而是以属性的方式来访问。所以
利用这个属性可以虚拟实现类属性的只读设置
7、静态方法staticmethod和类方法classmethod?
a)相同点:都可以用类名去调用,不需要实例化
b)不同点:
i.静态方法不需要传参数
ii.类方法需要传一个cls参数,
8、Instance和issubclass
Instance(obj,cls):检查一个obj是不是这个类实例
Issubclass(sub,supper):检查sub是不是super的子类
9、什么是反射?
a)可以用字符串的方式去访问对象的属性,调用对象的方法
*args和**kwargs称之是可变长参数,当函数需要传太多参数的时候可以用他们来代替
按照位置传参数冗余的部分,会被形参中的*保存成元组的形式赋值给arg。
按照关键字传参数冗余的部分,会被形参中的**保存成字典的形式赋值给kwargs
看是什么类型
不管是字符串,数字,还是列表都是传的引用,只不过最终现象不一样。可以通过id查看一下
3、什么是闭包?
答:内部函数包含对外部函数作用域(而非全局作用域)中变量的引用。
装饰器就是使用闭包的原理
4、怎么理解深浅拷贝?
深拷贝deepcopy:会拷贝父对象及其子对象
浅拷贝copy.copy():只会拷贝父对象,不会拷贝子对象
比如,如果一个对象里面又包含了另外一个对象,浅拷贝的时候只是把外部对象拷贝了一份
如果是深拷贝,会把外部的拷贝,吧内部的也拷贝
在什么时候用到了拷贝?
Request.GET是不一个QueryDict对象,是不可以修改的,需要加一个参数_mutable=True才可以修改,为了不影响其他的时候,我们可以拷贝一份,在做修改。
5、编码问题
Python3中的字符串是unicode
Python2中的字符串是字节
6、装饰器是什么?什么时候用过?
答:在不改变原有代码的基础上在执行之前或者执行之后做点操作
Flask的路由是用装饰器做的,flask的路由本质
用户认证的时候也用了装饰器,但是如果视图多的话可以用中间件的形式
装饰器的执行流程是什么样的?
答:
7、谈谈你理解的函数式编程:
Filter():
Map():
Reduce():
8、什么是可迭代对象?迭代器?生成器?
答:可迭代对象:含有__iter__的就是可迭代对象,返回一个迭代器
迭代器:含有__next__方法的就是迭代器,只能往前更新迭代,不能往后退。
生成器:基于函数+yield实现,即可以取值,也可以生成值,它也有一个__next__方法,具有迭代器的特性。返回一个生成器
你在哪里用过生成器?
答:在Crm中,获取返回的数据需如果不是自己想要的格式,可以进行二次加工,再在模板中循环展示时,可使用生成器减少循环。
9、为什么要有作用域?
作用域也就是作用范围,为了函数内的变量不影响到全局
global:强制转换成全局变量
nonlocal:让内部函数中的变量在上一层函数中生效,如果上一层函数中没有,就修改上上层的,依次类推,但是不会修改全局的
lambda表达式也叫做匿名函数(一些简单的需要用函数去解决的问题)
print('\n'.join(''.join(['%s*%s=%-3s'%(i,j,i*j)forjinrange(1,i+1)])foriinrange(1,10)))
答:API就是接口,提供的url,接口有两个用途:
1、为别人提供服务
2、前后端分离、一个写vue、一个写后端,他们之间是通过发送ajax请求
答:1、如果更新了数据,web端页面也要改,后端也要改,重复开发了
2、用前端框架开发的时候用的是vue框架,用vue框架搭建速度比较快
3、专门为它提供json数据
答:之前我们是没有用restapi规范的,都是通过django的url自己来做的,后来我们选择用了restapi,用了restapi就得遵循他的规范,比如
URL:通过method不同来区分不同的行为,比如get,post,put,patch,delete等
版本:
可以放在url上,也可以放到请求头中(但是我们一般不这样做),也可以放在子域名上(放在子域名上会存在跨域的问题,)
Method
Get:获取数据
Post:创建数据
Patch:部分修改
Put:全部修改
DELETE:删除数据
Options:如果有跨域,会先发一个option请求,先做预检,完了在执行自己发的请求
状态码,不同的请求会有不同的状态码
200:响应成功
302:重定向
403:Forbidden
404:找不到页面
500:服务端代码有误
筛选条件,如果记录的数据过多,服务器本可能都将他们返回给用户,API应该提供参数,过滤返回结果。
错误信息
hypermediaapi:超链接
{
id:1,
name"8级",
}
4、你们什么时候用的版本?
答:在更新迭代的时候,可以用到版本,当一期的版本开发完,二期的版本开发完,可以通过版本来做
答:我们一开始是没有用restfulframework,用django也能实现。不过它为我们提供了一些api接口,如果用django写的话就得自己写装饰器,中间件什么的,但是它为我们事先提供了一部分接口,常用的有认证,权限的判断,访问频率限制等,我们只需要按照人家的规范,只需要写几个类就好了,或者在配置文件里面配置一下就好了,不用我们自己在写装饰器,中间件什么的了,根据他的规范来写,尤其是在用户访问频率限制的时候,人家里面都已经封装好了,我们直接调用它的方法就行了。
'DEFAULT_THROTTLE_RATES':{
'xxx':'2/minute'#2分钟
答:1、他为我们实现了一些功能
3、说说restfulframework的原理?
答:我们写的时候是基于CBV模式写的,这个和django中的CBV是一样的,请求先进来会走dispatch方法,根据请求方法不同反射执行不同的方法。而djangorestframework里面的五大功能,都是放在dispath里面实现的。
我们写的类是继承APIView的View,去执行它的dispatch(先找自己的,自己没有就找父类的。)
为什么请求一进来就执行dispatch方法?
请求进来到达路由.as_view(),在as_view里面return了一个view函数
请求进来先执行一个view函数
obj=cls()#就是CBV实例化的对象
returnself.dispatch()#最终返回了一个dispatch,所以请求一进来就执行dispatch了
执行dispath流程:
封装request
版本
认证
类
classMyAuthentcate(BaseAuthentication):'''检查用户是否存在,如果存在就返回user和auth,如果没有就返回'''defauthenticate(self,request):token=request.query_params.get('token')obj=models.UserInfo.objects.filter(token=token).first()ifobj:return(obj.username,obj.token)returnNone#表示我不处理defauthenticate_header(self,request):pass#这个函数是验证不成功的时候执行的函数返回值
可以有三种返回值
ReturnNone#表示不处理
Return(user,auth)#认证成功后返回用户信息
Raise异常#也可以抛异常
配置
单独视图
classIndexView(APIView):authentication_classes=[MyAuthentication,]
全局配置
REST_FRAMEWORK={'UNAUTHENTICATED_USER':None,#表示是匿名用户'UNAUTHENTICATED_TOKEN':None,"DEFAULT_AUTHENTICATION_CLASSES":["app02.utils.MyAuthentication",],}
classMyPermission(BasePermission):message='无权访问'defhas_permission(self,request,view):ifrequest.user:returnTrue#true表示有权限returnFalse#false表示无权限defhas_object_permission(self,request,view):pass返回值
ReturnTrue有权限
ReturnFalse无权限
Returnexceptiions.PermissionDenied(detail=’错误信息’)#自己指定错误信息
配置视图classIndexView(APIView):permission_classes=[MyPermission,]全局REST_FRAMEWORK={"DEFAULT_PERMISSION_CLASSES":[#"app02.utils.MyPermission",],}
限流
allow_request()/wait()PS:scope=’wdp_user’
返回值
ReturnTrue不限制
ReturnFalse限制
视图:classIndexView(APIView):
throttle_classes=[AnonThrottle,UserThrottle,]
defget(self,request,*args,**kwargs):
self.dispatch
returnResponse('访问首页')
全局
REST_FRAMEWORK={
"DEFAULT_THROTTLE_CLASSES":[],
'wdp_anon':'5/minute',
'wdp_user':'10/minute',
序列化
视图
、APIView
GenericAPIView(APIView)
GenericViewSet(ViewSetMixin,generics.GenericAPIView)
ModelViewSet(mixins.CreateModelMixin增
,mixins.RetrieveModelMixin,查一条
mixins.UpdateModelMixin,修改
mixins.DestroyModelMixin,删除
mixins.ListModelMixin,GenericViewSet查多条
)
解析器
如果发送的是json数据的话,可以在request.data里面取值
而django中会在request.body中取值,获取的值是bytes类型的,还的decode,loads一下,明显djangorestframwork明显方便的多
分页
基于limitoffset做分页
基于页码做分页
基于cursor做分页
方式a、记录当前访问页数的数据id
路由
渲染器
进程与线程的表示:
Process进程
Threading线程
答:切换+保存状态
并发:看起来是同时运行的,在多个任务里面来回切,切的时候保存状态、遇到IO阻塞的时候才切,
工作的最小单位是进程;一个进程里面可以开多个线程;
而协程是程序员可以人为的分配先执行这个后执行那个
进程:一个程序正在运行的过程
线程:一个流水线工作的过程,一条流水线必须属于一个车间,而这个车间的工作过程就是进程。所以说进程里面是包括线程的。所以进程里面真正干活的是线程
协程:一个任务运行完,切换到另一个任务。单线程下实现并发
答:协程是一个任务运行完,切到另一个任务,是程序员可以人为的分配先执行这个后执行那个
单线程下实现并发。
答:在多线程开发过程中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者处理能力大于生产者,那么消费者就等生产者。就这样形成了互相等的形式。为了解决这个为题所以才引进了生产者和消费者模型
答:使用生产者和消费者模型能够绝大多数的解决并发问题
答:生产者消费者模型是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通信,而是通过阻塞队列进行通信。所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不直接找生产者要,而是直接从阻塞队列里面去取数据。队列就相当于一个缓存区,平衡了生产者和消费者的处理能力。
答:是通过Manager来实现数据共享的。
IPC(进程间的三种通信方式)
Queue队列:队列类似于一条管道,元素先进先出。
Pipe管道:管道相当于对列,但是管道不自动加锁
Manager共享数据:共享数据也没有加锁的功能
因为进程之间的数据是隔离的,要想进行数据共享就得通过以上的方式来实现数据共享,推荐用对列的方式
而线程之间的数据是共享的,如果想实现数据隔离怎么实现?
答:本地线程:保证每个线程都只有自己的一份数据,在操作时不会影响别人的,即使是多线程,自己的值也是互相隔离的。
答:开多进程,开多线程,进程池和线程池(current.future模块),协程gevent:单线程下实现并发
答:同步:提交完任务后在原地等着
异步:提交完任务之后就走了,不用等了,吧结果丢给了回调函数
答:部署的时候用过,但是代码里面没有涉及到大量的计算。
计算密集型的用多进程
IO密集型的开多线程
人为控制的线程执行流程,先执行这个再执行那个
可以通过yield自己控制,
Greenlet
基于Gevent实现协程
答:1、创建线程比创建进程开销小(开一个进程、里面就有空间了,而线程在进程里面)
2、多线程一定是在一个进程里面开启的,共享进程里面的数据
3、线程启动速度快
4、同一进程下的多线程共享进程里面的数据
多个进程之间的内存空间是数据隔离的
5、线程可以跟它所在的进程之内的线程通信
GIL与Lock锁是两把锁,他们保护的数据不一样,GIT锁是解释器级别的(所以保护的是解释器级别的数据,比如垃圾回收的数据),Lock是保护用户自己开发的应用程序的数据,很明显GIL不负责这件事。
为了解决死锁现象,加了一把Rlock锁。死锁现象就是形成了互相等待的过程
简单描述GIL对Python性能的影响
使Python不能真正意义上的多线程,同一时刻只能有一个线程运行。
5.1Python的GIL在单核情况下对性能的影响可以忽略不计,几乎没有。
5.2Python由于其GIL的存在在多核CPU的情况下Thread的表现真的是非常的糟糕,但是Process则不受GIL的影响。
5.3Python内置的数据类是不适合用于大量的数学计算的,当然这也不仅仅是Python的问题,其它完全面向对象的语言都有这个问题,要进行大量的数学计算就要用把代码移到C/C++中去实现,这样不仅可以去除gil的影响,更可以让性能获得几十倍上百倍的提升,或者用numpy之类的扩展在执行科学计算时也可以让性能大幅的提升。
5.4Python慢其实就是慢在数字计算上,想想就知道,如果每一个数字都是一个对象,在计算的时候就免不了不断的为对象申请内存,释放内存,速度肯定就慢下来。
5.5但是,Python对数据结构的操作是非常高效的,像Python内置的强大的dict,str,list等类,不是说大话,其处理的速度真的可以和C媲美,因为它们的实现本身就是用C实现的。我们在编程刚入门的时候就被告知:数据结构+算法=程序,这个道理也许只会在用Python这样的语言时才会有更切身的体会。
5.7但是,记住一点,不要过早的对程序进行优化,过早优化是罪恶之源---DonaldKnuth。前期开发应该把注意力放在功能实现以及代码的可读性和可维护性上来。
5.8最后,愿以一句话作为本篇文件的结束语:都说爱一个人就要爱他(她)的全部,包括他(她)的缺点,对人如此,对物呢?
数据共享就会有竞争,所以考虑加锁。让串行执行,速度慢,数据安全。
如果不加锁,并发执行,速度快,数据不安全。
Importthreding
Mutex=theading.lock()
Mutex.aquire()#加锁
‘’对公共数据的操作’’’
Mutex.release()#释放锁
TCp:双向链接,客户端向服务端发送消息后,等待服务端回复消息后才算发送成功。
缺点:速度慢
优点:可靠
UDP:没有链接、直接发送
优点:速度快
缺点:不可靠
19、三次握手(连接)和四次挥手(断开):
三次握手的目的:建立双向通信链路。SYN代表客户端向服务端发送的一个请求,ACK代表服务端向客户端发送的回应。
三次握手就像谈恋爱确定关系一样,四次挥手就像分手一样。此处只是打比方而已。
1、物理层:常见的物理设备:中继器、集线器、双绞线
功能:主要基于电器特性发送高低电压,高电压对应数字1,低电压对应数字0(提供电信号)
2、数据链路层:网桥、以太网交换机、网卡
功能:定义了电信号的分组方式
3、网路层:路由器、三层交换机
功能:引入一套新的地址用来区分不同的广播域/子网,这套地址即网络地址。
4、传输层:四层交换机、四层的路由器
功能:建立端口到端口的通信。
5、会话层
6、表示层
7、应用层
功能:规定应用程序的数据格式。
7.IPC
进程之间的通信有两种实现方式:管道和队列
进程之间的数据共享:Manager
tasklist查看进程
tasklist|findstrpycharm#(findstr是进行过滤的),|就是管道(tasklist执行的内容就放到管道里面了,管道后面的findstrpycharm就接收了)
进程间通信技术包括消息传递、同步、共享内存和远程过程调用(RFC)。IPC是一种标准的Unix通信机制
线程之间数据数据隔离:
本地线程:保证每个线程都只有自己的一份数据,在操作时不会影响别人的,即使是多线程,自己的值也是互相隔离的
8.lock与rlock,信号量也是一种锁
Lock是互斥锁
Rlock是为了解决死锁问题出现的
死锁是指是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
信号量:是产生的一对进程/线程,即产生了多个任务都去抢那一把锁。
总结:
1.多核也就是多个cpu
(1)cpu越多,提高的是计算的性能
(2)如果程序是IO操作的时候(多核和单核是一样的),再多的cpu也没有什么意义。
2.实现并发
(1)
数据库的范式:
第一范式:是指数据库表中的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性
第二范式:第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。
Mysiam:支持全文索引,不支持行锁,支持表锁
Innodb:支持事务,支持行锁,支持表锁
行锁:根据主键找到数据
Select*fromtb2wherenid=3forupdate;
表锁:
根据主键,未找到数据
Select*fromtb2wherenid=30forupdate;
根据主键,数据不明确
Select*fromtb2wherenid<2forupdate;
Select*fromtb2wherenid!=3forupdate;
根据非主键查找
Select*fromtb2wherename=’alex’forupdate;
当数据量越来越大的时候,查询速度会越来越慢,这就可以用加索引的方式提高查询速度
索引分类?
1、普通索引index
2、主键索引primarykey
3、唯一索引unique
4、联合索引(遵循最左匹配原则:mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配)
Primarykey(id,name)联合主键索引
Unique(id,name)联合唯一索引
Index(id,name)联合普通索引
5、覆盖索引:在索引表里面吧所有的值拿到
6、合并索引:两个单独的索引合起来一起用
索引命中:
创建索引
索引的种类?
Hash类型的索引:查询单条快,范围查询慢。
Btree类型的索引:b+树,层次越多,数据量指数级增长(ennodb默认的就是Btree类型)
创建索引,未命中
命中:相当于精确查询。。。in,like就不命中
排序条件为索引,则select字段必须也是索引字段,否则无法命中
5、在django的model操作,怎么提高性能?
Select_related:一对多使用,查询主动做连表操作
Prefetch_related:多对多或者一对多的时候使用,不做连表,做多次查询
6、数据库怎么创建索引?
createindexaccount_countontable_name字段名
怎么创建组合索引?
createindexaccount_countontable_name(字段名,字段名)
7、mysql有那些数据类型?
a)数字
b)字符
c)日期
d)枚举和集合
减少FK
允许数据冗余
不经常更改的数据放入内存models中的choice
Select*
Pymysql
Django中默认的是MySQldb,如何改成pymysql。
放在项目的__init__里面Pymysql.install_as_mysqldb()
函数、视图、存储过程、触发器都是存在数据库的。
关系型数据库:mysql、oracle
非关系型数据库:redis、memcache
Redis和memcache都是在内存中存放的
Redis是支持持久化的,memcache是不支持的,相对于memchache慢一点。但是比mysql关系型数据库快的多。因为mysql的数据是存在硬盘的,redis是存在内存中的
(1)Redis:Key:value键值对
Name:’yaa’,
Name:[]
Name:{“”:””}#散列表
Name:{}#集合
Name:””#字符串
Memchache:key:value
Name:””#只支持字符串
(2)Redis是支持持久化的,memcache是不支持的,相对于memchache慢一点
(3)Memchache一断电就数据没有了,redis支持持久化可以存一点数据,所以安全性不高
Redis:优点是存在内存、速度快;缺点是不安全
Mysql:优点是安全,是存在硬盘的;缺点是查询速度慢。
本质通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据。
一定要注意sql注入
Mysql数据备份:
视图:
视图是一个虚拟表(非真实存在),其本质是【根据SQL语句获取动态的数据集,并为其命名】,用户使用时只需使用【名称】即可获取结果集,可以将该结果集当做表来使用。
但是视图有明显的效率问题,并且视图是存放在数据库中,如果我们程序中使用的sql过分依赖数据库中的视图,即强耦合,那就意味着扩展sql极为不便,因此不推荐使用。
触发器:
--触发器:某种程序触发了工具的运行
--触发器不能主动调用,只有触发了某种行为才会调用触发器的执行
--插入一条记录就触发一次
--还是建议不要用触发器,因为这是BDA管理的,还是不如你在程序里面直接写比较方便
事务:
--事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,--即可回滚到原来的状态,从而保证数据库数据完整性。--事务也就是要么都成功,要么都不成功--事务就是由一堆sql语句组成的
存储过程:
存储过程包含了一系列可执行的sql语句,存储过程存放于MySQL中,通过调用它的名字可以执行其内部的一堆sql
--存储过程的优点:--1.程序与数据实现解耦
--2.减少网络传输的数据量
--但是看似很完美,还是不推荐你使用
#方式一:MySQL:存储过程
程序:调用存储过程
#方式二:
MySQL:
程序:纯SQL语句
#方式三:
MySQL:
程序:类和对象,即ORM(本质还是纯SQL语句)
数据库的增删改查(sql):
增:createdatabasedb1;
删:dropdatabasedb1;
改:alterdatabasedb1charsetutf8;
查:showdatabases;
表的增删改查:
增:createtablet1(idint,namechar);
删:droptablet1;
改:
插入数据:insetintotest(id,name)values(1,’*’)
查:showtables;
Showcreatetablet1;查看指定的表
数据库的指定引擎:
Innodb:出现2个文件
Myisam:会出现3个文件
Memory:只有表结构没有表数据,是创建到内存中的
查看MySQL的引擎Showengines:
查看默认引擎:showvariableslike'%storage_engine%';
查看当前表的引擎:showcreatetable表名;
创建用户:
Createuser‘egon’@‘192.168.1.%’identifiedby‘123’
grantselecton*.*‘egon’@’localhost’identifiedby
1、Django的缓存机制?
Django默认有缓存机制,它能为我们做什么事情?
6中缓存方式
1、内存缓存
2、文件缓存
3、开发调试缓存
4、数据库缓存
5、Memcache缓存
经常使用的有文件缓存和mecache缓存
3.Django基本命令:1pip3installdjango
有名分组和无名分组:(P
视图返回:HTTPresponserenderresponse
获取多个键值对的时候用:request.POST.getlist("hobby")在模板中:复杂的数据结构用句点符.句点符也可以用来引用对象的方法.HTTP协议:是属于应用层的面向对象的协议特点:简单快速灵活无连接无状态Http协议的格式:请求首行请求头信息空行请求体HTTP默认的请求方法就是GET*没有请求体*数据量有限制!*GET请求数据会暴露在浏览器的地址栏中
GET请求常用的操作:1.在浏览器的地址栏中直接给出URL,那么就一定是GET请求2.点击页面上的超链接也一定是GET请求3.提交表单时,表单默认使用GET请求,但可以设置为POST
GET和POST的区别
1.GET提交的数据会放在URL之后,以分割URL和传输数据,参数之间以&相连,如EditPosts.aspxname=test1&id=123456.POST方法是把提交的数据放在HTTP包的Body中.
2.GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
3.GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值。
Wsgiwsgiref实现这个方法MTV模型:M代表的是ModelT代表的是TemplateV代表是的View模板层:模板=html+模板语法模板继承用extends数据库改为mysql需要改两个方面:第一是注销掉原来的数据库,改为mysql第二步是:在项目的__init__里面加上两句importmysqlpymysql.instsll_as_MySQLdb()ORM:13个API和2个补充onlyderfervalues拿到的是字典values_list拿到的是元祖
2.Django生命周期:wasgi中间件路由视图ORM渲染
什么是本地线程?
什么是上下文管理?
本质:每一个线程都会创建一个
Django大而全:
无socket,依赖于第三方wsgiref模块实现了wsigi协议,中间件,视图(CBV,FBV)
模板、cookie、session、ORM、Admin、Form、缓存、信号、序列化
Flask小而精:
无socket,依赖于是第三方werkzeug模块实现wsgi协议,中间件(扩展),视图(CBV,FBV)
无模板、用的是第三方JinJa2模板,无ORM、cookie、session(比较弱)
缺点:不安全
8、路由参数
redirect_to:直接重定向,原url有参数时,跳转使也得传参,注意:不用加类型
@app.route('/test',strict_slashes=True)#当为True时,url后面必须不加斜杠
#===============子域名访问============
@app.route("/static_index",subdomain="admin")
扩展Flask的路由系统,让他支持正则,这个类必须这样写,必须去继承BaseConverter
@app.route('/index/
-request-request.form#POST请求-request.args#GET请求字典形式的-request.querystring#GET请求,bytes形式的-response-returnrender_tempalte()-returnredirect()-return""v=make_response(返回值)#把返回的值包在了这个函数里面-session-存在浏览器上,并且是加密的-依赖于:secret_key5、闪现的本质是什么?1、本质:flash是基于session创建的,flash支持往里边放值,只要你取一下就没有了,相当于pop了一下。不仅把值取走,而且把session里的东西去掉
6、flask里面的扩展,相当于django中的中间件
@app.before_requestdefprocess_request1():print('process_request1')@app.after_requestdefprocess_response1(response):print('process_response1')returnresponse7、蓝图(flask中多py文件拆分都要用到蓝图)
创建Local类:
线程或协程唯一标识:{'stack':[request],'xxx':[session,]},
线程或协程唯一标识:{'stack':[]},
b、上下文管理的本质
每一个线程都会创建一个上面那样的结构,
列表中的数据,请求完成之后,将request从列表中移除
12、witform组件WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证14、flask-sessionflask-session是flask框架的session组件,由于原来flask内置session使用签名cookie保存,该组件则将支持session保存到多个地方,如:
冒泡排序:就是两层for循环一层控制的是趟数,一层是进行比较
选择排序:就是每次选择比当前还小的值进行交换还有一步就是要判断那个值是否改变了,只有改变了才需要交换下
插入排序:分为有序区和无序区每次用拿到的数据和有序区的所有数据进行比较大小
快排:首先,找到第一个值作为中间值,左边都比它小右边都比它大,然后在使用整个快排方法对左边和右边进行递归调用。
归并排序:也是用到了递归调用;假设分为2部分,在生成一个列表,把两个列表的数据按照大小放入,剩下的一起放入。
堆排序:先创建堆,然后找它的左子节点,判断是否比子节点大如果大接着继续往下判断,如果过没有就把那个值放在子节点上(干部)
思路:列表中两个相邻的数比较大小,如果前边的比后边的大,那么这两个就互换位置defbubblr_sort(li):
foriinrange(1,len(li)-1):#表示趟数change=Trueforjinrange(len(li)-i):#表示无序区,无序区的范围为0,len(li)-iifli[j]>li[j+1]:li[j],li[j+1]=li[j+1],li[j]change=Trueifnotchange:returnli=list(range(10))importrandomrandom.shuffle(li)print(li)bubblr_sort(li)print(li)
三种排序算法的缺点
a)快速排序:极端情况下排序效率低
b)归并排序:需要额外的内存开销
c)堆排序:在快的排序算法中相对较慢
挨着换的稳定,不挨着换的不稳定
1、你对函数式编程和面向对象编程的理解?
函数式编程是:将公共能功能编写成一个函数,通过参数的不同来产出不同的结果
面向对象编程是:有三大特性:封装、继承、多态
多态:鸭子类型,由于Python是非强类型的,例如传入的值不管是什么,只要有我自己想调用的方法就行了,本身就是多态的。
方法和属性的封装
继承:在Python中是有多继承的,当前类中没有方法或者其他字段,去基类中查找。
2、经典类和新式类的区别?
经典类:不继承obj
Python3中只有新式类
不管是字符串,数字,还是列表都是传的引用,只不过最终现象不一样。
10、什么是闭包?
答:内部函数包含对外部函数作用域而非全局作用域名字的引用。
装饰器就是必用闭包的原理
11、怎么理解深浅拷贝?
12、编码问题
13、装饰器是什么?什么时候用过?
Flask的路由是用装饰器做的
14、什么是可迭代对象?迭代器?生成器?
15、
2、为什么学Python?
(1)大学的时候学的测试,出去直接找工作有点难度,因为大学学的都是些基础,没有实战的项目,找工作也不好找,就想着培训一下,后来网上搜了一下,看python挺火的
工资待遇啥的也都不错,心里就想着培训这个,所以就学习了python
3、字符串常见的方法有哪些?
答:strip(),split(),startwiths(),index(),endwiths(),
4、列表常见方法?
5、字典常见方法?
6、元组常见方法?
7、结合常见方法?
8、Collections模块
9、unicode和utf-8的区别?
10、Python2和Python3的区别?
(4)Python2中的文件读取Xreadlines和Python3中的readline
10.字符编码
如何让计算机读懂人类的字符?
必须经过一个过程:
#字符--------(翻译过程)------->数字
#这个过程实际就是一个字符如何对应一个特定数字的标准,这个标准称之为字符编码
Ascii:用1个字节(8位二进制)代表一个字符8bit可以表示0-2**8-1种变化,即可表示256个字符
Unicode(定长):常用2个字节(16位二进制)代表一个字符,生僻字需要用4个字节
Gbk:2Bytes代表一个中文字符,1Bytes表示一个英文字符
Utf-8(可变长):对英文字符只用1Bytes,对中文字符采用3Bytes,
总结:内存中统一采用Unicode,浪费空间来换取可以转换成任意编码(不乱码),硬盘可以采用各种编码,如utf-8,保证存放于硬盘或者基于网络传输数据的数据量很小,提交传输效率与稳定性。
以什么编码存的,就要以什么编码取出
Ps:内存固定使用unicode编码,我们可以控制的编码是往硬盘存放或者基于网络传输
数据最先产生于内存是unicode格式,要想传输需要转成bytes格式。
Unicode–》encode(utf-8)—》bytes
拿到bytes,就可以往文件内存放或者基于网络传输
Bytes---》decode(gbk)—》unicode
Python3中字符串被识别成unicode
Python3中的字符串encode得到bytes
Python2中的字符串就是bytes
Python2中在字符串前加u就是unicode
Json/pickle
importsys
print(sys.argv)#实现从程序外部向程序传递参数。(在命令行里面输打开路径执行)
name=sys.argv[1]#命令行参数List,第一个元素是程序的本身路径
password=sys.argv[2]
ifname=='egon'andpassword=='123':
print('继续执行程序')
else:
exit()
sys.exit()#退出程序,正常退出时exit(0)
print(sys.version)#获取python解释的版本信息
print(sys.maxsize)#最大能表示的数,与系统多少位有关
print(sys.path)#返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
print(sys.platform)#返回操作系统平台名称
OS模块
os.getcwd()获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")改变当前脚本工作目录;相当于shell下cd
os.curdir返回当前目录:('.')
os.pardir获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2')可生成多层递归目录
os.removedirs('dirname1')若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')生成单级目录;相当于shell中mkdirdirname
os.rmdir('dirname')删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdirdirname
os.listdir('dirname')列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()删除一个文件
os.rename("oldname","newname")重命名文件/目录
os.stat('path/filename')获取文件/目录信息
os.sep输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep输出用于分割文件路径的字符串win下为;,Linux下为:
os.name输出字符串指示当前使用平台。win->'nt';Linux->'posix'
os.system("bashcommand")运行shell命令,直接显示
os.popen("bashcommand)运行shell命令,获取执行结果
os.environ获取系统环境变量
os.path
os.path.abspath(path)返回path规范化的绝对路径os.path.split(path)将path分割成目录和文件名二元组返回os.path.dirname(path)返回path的目录。其实就是os.path.split(path)的第一个元素os.path.basename(path)返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。
即os.path.split(path)的第二个元素
os.path.exists(path)如果path存在,返回True;如果path不存在,返回False
Re:
Haslib:
Subprocess:执行系统命令
Requests:
Befautiful
10、正则里面有哪些方法?
Match:只是从字符串的开头进行匹配,也就是说只有在索引为0的位置匹配成功的话才有返回值,如果不是开始位置匹配的话,返回值为none
Search:会把整个字符串扫描一遍,并返回第一个成功匹配的值
Findall
贪婪匹配
常用正则:
手机号
Ip
答:就是浏览器和服务器之间进行“沟通”的一种规范。
答:简单快速,灵活,无链接,无状态
答:get,post,delete,put,patch,options,head,connect
我常用的就是get,post,delete,put,patch,options,这几个
在restframework里面写接口的时候,用了这些方法
HTTP请求默认的请求方法是GET请求
没有请求体;数据量有限制;GET请求请求的数据会放在url上
有请求体,
15、GET请求和POST请求的区别?
a、GET提交的数据会放在URL之后,以分割URL和传输数据,参数之间以&相连,如EditPosts.aspxname=test1&id=123456.POST方法是把提交的数据放在HTTP包的Body中.
b、GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
c、GET方式需要使用Request.GET来取得变量的值,而POST方式通过Request.POST来获取变量的值。
1、请求头和请求体之间是通过\r\n\r\n来分割的
2、请求体之间是一个\r\n
3、Get无请求体
4、无状态、短连接:socket请求响应断开
5、请求头代表的意义:
b)Referer:防盗链
c)Content-type:请求体是什么格式?
1、保障系统(个人博客,报障系统)
项目背景:需要对公司内网运维工作绩效考评,以及对于内网运维工作效率的提高创建知识库的功能,所以才开发这么一个系统
周期:一个人,三周左右
有两大功能:
1、员工填写故障单
#公司的员工发送问题,内网运维接单。
3、常见知识库分类和筛选:
一些常用的问题写到知识库里面,自己去查也就解决了。
常见问题还有分类
4、基于HighChar实现员工工作绩效的对比
外网运维:公司的所有网站不挂掉,都是外网运维干的
内网运维:比如你的电脑连不上网络,等是内网运维干的
2、CRM系统(也可以更改成基于rbac的xxx的管理系统)
以教育行业为例
描述:基于rbac的使用,对系统人员进行权限控制对学校、老师、班级和销售进行统一管理,其中涉及销售的报表和跟进记录,并对销售人员成单比进行统计,这都是可以通过highchart做出来的,以及班级和评分的管理,其中还有对公司会议室开发的会议室预定。
周期:1-2人,3-6月
功能:
1、基于中间件和session实现自定制rbac权限组件,粒度到按钮级别。(目标是开发一个公共的组件),用了那些表,流程
2、基于BootStrap实现页面展示
4、基于HighChart对销售业绩进行可视化显示
5、参考Django源码实现自定义stark组件开发,并完成自定制,组合查询等功能
6、通过django-redis实现session存储
7、基于Form实现可定制的调查问卷
业务:
对于销售来说有一下权限,比如:
基于MOdelForm实现客户数据录入
对于销售经理,可以查看人员成单记录
班级管理
对于班主任:主要做班级管理,沟通记录,问卷(对于问卷也是有权限管理的)
老师:上课记录,检查祖业,上传作业,初始化班级
外包到别人公司给他们公司做的,或者给自己公司做的。
3、路飞学城(在线教育平台)
用Git进行协同开发。
周期:半年
团队:
1个UI,1个前端,4个后端,
基于极验实现的动态验证码
在线视频播放是用CC视频。
基于restframework实现API接口
4、权限管理系统
目的:生成一个独立的组件,到哪都能用
1、所涉及的表
五个类,七张表
用户表
权限表
角色表
组表
菜单表
角色权限表
用户角色表
2、实现的功能:
b、判断有没有添加权限,有没有删除权限,有没有编辑权限,粒度到了按钮
C、生成菜单:并且让这些菜单分级显示默认展开的组内菜单是红色的。如果是非菜单,默认选中原菜单
具体实现:在设计表的时候设计了一个组内菜单(自关联),当是NULL的时候就说明是可以作为菜单的。