1、手写helloworld
2、配置文件:中间件、可拓展实例:短信、微信、邮件
3、闪现
4、路由系统:装饰器(url、endpoint、method、servername)、自定义路由(装饰器的位置、endpoint重名2中方式解决)
5、请求扩展:请求、错误处理、定义模版函数
6、蓝图:提供目录,实现多文件程序。对文件进行归类,每一个蓝图就是一个小功能。每一个蓝图中都可以before_request
7、请求响应相关:make_response接下来可以设置了set_cookie
8、中间件:
9、上下文:threading.local 为每个线程分配内存空间存储数据
防止多线程修改数据造成数据混乱
falsk里边是为了支持携程自定义了这个local类实现了上边的功能,搞了个字典,为每一个线程整了个唯一标识,换了种init 中的方法不常用setattr的方法, greenlet导入 get_ident作为storyge的key
10、偏函数:import functiontools
Def func(a1.a2)
Print(a1,a2)
v= functiontools.partial(func,666)共同为函数传递参数,穿了一个参数,只需要在传递一个,关键字参数或者位置参数
11、对象中存在内置方法__开头的,面向对象中所有的__. __ 实现时,都会执行其中对应的方法
12、from itertools import chain
Def f1(x):
Return x + 1
func1_list = [f1, lambda x : x -1 ]
Def f2(x):
Return x + 10
把三个函数一块执行,chain中必须是可叠戴对象
用new_func_list = chain([f2] , func1_list)
用于before_request中使用一块都要执行,拼接值
12、到31了
13、flask快速入门、配置文件、路由系统、模版语言、请求与相应、session和cookie、闪现、蓝图、请求扩展(类似django中间件)、中间件
14、装饰器:
session和cookie原理:随机字符串放到reids中或者memcache中作为键,自己的内容作为值
继承字典:在原有的基础上多做一些操作
配置文件和全局变量要大写
15、框架的介绍:
django:重武器,内部包含了非常多的组件:orm,form,modelform,缓存,中间件,信号,session
flask:短小精悍,可以写简单应用,内部没有太多组件,第三方组件非常丰富
tornado(node.js):异步非阻塞,一个线程执行1000个任务
16、flask中用的是werkzeug实现的wsgi,run_simple(‘localhost’,4000,hello)
但是本质的本质就是通过socket来做的监听和发送来获取的
Import socket
Def handle_request(client):
Buf = client.recv(1024)
client.send(‘http/1.1 200 ok\r\n\r\)
Client.send(‘hello seven’)
Def main():
Sock = socket.socket(socket.AF_INEF,socket.SOCKET.STREAM)
Socket.bind(‘localhost’,8000)
Socket.listen(5)
While True:
Connection,address = sock.accept()
handle_request(connection)
Connection.close()
If __name__ == ‘__main__’:
main()
17、请求上下文:启动之后执行如下问题:
上下文第一步:三个类第一步ctx中:把请求相关的东西进行了一次封装还没有放到local中了!!
flask(处理请求相关所有东西)、requestcontext(包含请求相关东西、session、flash、url等)、request(因为请求相关东西比较多就放到这个类中进行保存了)这三个类就把请求流程给走通了
上下文第二步:ctx.push()将对象放到local中(每个线程和每个携程独立的空间)。涉及到两个类:localstack和local
启动之前第一步实例ocalstack()先执行__init__执行local()的init实例话龙哥storage空的
上下文第三步:创建localprocy对象,执行里面的构造方法。 Request是全局变量:在程序刚启动的时候就创建了,只要print(request)或者request.method就会执行localproxy.__str__方法调用自己的get_current_object函数启动然后调用local这个参数是个函数就会执行这个函数,然后通过request_local_stack.top从local中取request的值
上下文第四步:request.method. 这就会调用__getattr__方法
上下文第五部最后一步:调用ctx.aoto_pop() 把请求从local中删除
18、dbutils数据库连接池:
模式:创建n个链接,多线程来时,去获取。线程池都是可以被共享的,链接完事后下一个可以在链接!pool = pooleddb( ). Coon.close()这不是真正的关闭链接,只是把链接放回了连接池中,
创建一个连接池:单利模式
19、用staticmethod时候只有在类不用实例化的时候才能使用,直接类调用就可以了
20、信号:注册触发、智能执行不能终止无返回值
21、强制获取类里面的私有字段:obj.__foo__age
22、应用上下文:
分两个大类两个context对象:
请求顺序:app.__call__
app.wsgi_app
App.request_class
App.run
ctx = requestcontext
Ctx.request
Ctx.session
app_ctx = app context
app_ctx.app
app_ctx.g。 (可以中间件判断权限有啥)
都是从localproxy中拿着4个参数对象
当两个进程也就是2个请求同时到来时,就有且仅有2个local,请求没来时是空的local,,会有好多唯一标识greenlet携程{stack:[ctx对象]}这个用列表的原因就是用列表创建出来的栈(写网站不会出线问题,写脚本的时候列表中 可能出现2个,因为可能会嵌套使用with)一般用于测试,其他情况列表永远只有一条数据
23、多app应用: 相当于在app前边做分发,蓝图相当于在app后边做分发
上下文管理还是一样的和单app
run_simple()请求进来会执行第三个参数加括号!
Dm = dispatch middleware(app1,{“/sec”:app2})
24、with 不用数据库连接池,显示数据库连接,先打开,在执行,在关闭
with sqlhelper() as. F: 会调用类中的 __enter__ 方法,f为其返回值
ogj.fetch()
完毕后会自动调用类的__exit__方法
面向对象可以封装多个对象,派生类中无法调用父类的私有字段
25、关联子查询:select id, name , (select max(id) in xxx) as mid from tb 必须保证子查询结果是一个数据(avg)
26、flask_sqlalchemy. 封装了配置文件、create_all生成数据库表(要读local中的信息所有要先有flask环境)、封装了继承了declarative_base、也包含了engine、帮你创建连接
27、pipreqs 把自己项目所需要的包自动放到requirements中去 在根目录执行pipreqs
./就会自动生成requirements
28、flask-script 用于实现类似于django的python manage.py rumserver 功能的东西。。还可以自定义命令@manager.command 用python manage.py 函数名+参数 相当于执行离线脚本,@manager.option(-n. —name. Dest = name).
@manager.option(-u. —url. Dest = url).关键字参数 相当于执行脚本!!!很重要
29、改数据库的表结构:引入第三方组件flask-migrate. Flask-wtf表单验form.validate()参数验证
30、url_for 为某一个资源生成url (静态资源、试图函数、upload获取)
Flask-upload 分组管理、保存文件、获取url可以让浏览器访问
App.config[‘upload_folder’] = ‘uploads’
Os.path.join(static_dir,app.config[‘upload_folder’])
第一步:配置上传文件的保存地址:app.config[‘upload_photos_dest’] = ‘app.config[abs_upload_folder]
第二步:view中声明类对象的实例用来管理上传集合:from-uploads import configure_uploads,uploadset,images扩展名,Photosus=uploadset(‘photos’,images)
第三步:configure_uploads(app,(photos,media))绑定两个对象,相当于注册
第四部:可以用save方法保存文件,用path服务器和ur浏览器l方法访问他们
Name = photoset.save(fs)storage, folder, name三个参数,返回文件名,参数有无folder就是中英文改成下划线问题
返回url:file_url = photoset.url(name)
#设置文件大小
app.config['MAX_CONTENT_LENGTH'] = 2*1024*1024
31、联合查询:
super_count =CompanyUserRoleModel.query.join(CompanyRoleModel,CompanyUserRoleModel.role_id==CompanyRoleModel.id)\
.filter(CompanyUserRoleModel.company_id==current_user.company_id)\
.filter(CompanyUserRoleModel.user_id==current_user.id)\
.filter(CompanyRoleModel.role_name=='超级管理员')\
.count()
创建一个新用户,同时将新用户关联到一家公司下,需要事物了
flush和commit区别:一般涉及到原子操作的时候用flush较多,然后绑定事物!!!!!!
> flush: 写数据库,但不提交,也就是事务未结束
> commit: 是先调用flush写数据库,然后提交,结束事务,并开始新的事务
32、模型操作:
Class trade info:
Def __init__(self,goods):
Self.total = 0
Self.trades = []
Self.__parse(goods)
Def __parse(self,goods):处理一组数据
self.toal = len(goods)
Self.trades = [self.__map_to_trade(sigle) for single in goods]
Def __map_to_trade(self,single):处理单个数据
If sigle.create_datetime:
Time = sigle.create_time.strftime(%Y-%m-%d)
Else:
Time = 未知
Return dict(
user_name = single.user.nickname,
Time = time
Id = sigle.id
)
@property
Def create_datetime(self):
If self.create_time:
Return date time.fromtimestamp(self.create_time)
Else:
Return none
33、basequery中的first_or_404()查询为空就抛出异常,页面出现notfound(通过abord抛出)—first—abort——httpexception(异常对象的基类)
可调用对象用处:1、简化对象方法的调用()就调用—call—的方法或者某个方法用的特别多 2、模糊了对象和函数的区别:统一调用的接口class a() class b(). func()
Def main(param):
统一调用。 就需要把a和b内部实现__call__方法
34、aop思想:把所有可能出现的情况集中到一个地方一个函数中
@web.app_errorhandler(404). 蓝图对象监控状态码为404,才会执行都返回这个页面
Def not_found(e): 可以实现任意的代码需求业务逻辑
Return render_template(‘404.html“),404
35、 return在函数和视图函数(返回response对象 )导入response= make_response()不同 (看headers头信息)
headers={content-type:text/plain。 /json
Location:http://www.bing.com
}
Response = make_response()
Response.headers = headers
Return response. 重定向
36、用urllib和request做用户请求:三元表达式简化代码或者if + return处理特例情况
class http:
Def get(self,url,return_json=True):
R = request.get(url)
If r.status_code = = 200:
If return_json:
Return r.json()
Else:
Return r.text
Else:
Rerun {}
37、方法是实例方法没用到self时没意义了,换成静态方法或类方法,用classmethod好
38、flask中的jsonify()其实就是api(就是json的形式)
39、request直接从flask导入使用 request.args【】是字典的一个子类(不可变的字典)调用to_dict就变成可变字典了
40、模型继承usermixin(封装了好多方法)
使用login_user(user,remember=true)一定时间免登录将用户票据写入到cookie中
导入login_manager = loginmanager
导入login_required 与get_user绑定查询主键用get. 用@login_manager.user_loader装饰器装饰绑定关系
可以导入current_user
41、注册form= formregister(). 请求的数据都存在了form中了,form.validate 参数验证然后通过form.data取到里面的信息,通过form.error取到里面的错误信息。注意_password = column(‘password’)要存一个字符串,通过@password_setattr来写设置password的信息,@property读取函数内容
42、assert condition. =====. if not condition:
raise AssertionError()
43、with app.app_context():
a = current_app
D = current_app.config[debug] 上下文管理器可以用with语句。内部实现了__enter__,__exit__方法, with后边是上下文表达式,返回上下文管理器
44、只有在请求中才会flask自动入栈,在request请求入栈之前会让flask入栈
45、
1、连接数据库
2、sql
3、释放资源
用try except. Finally 实现最后释放资源在finaly中执行
更优雅方式用with上下文管理器实现
连接数据库写在__enter__中
sql写在with语句代码块中
释放资源写在__exit__中
文件读写:
Try:
f = open(r’’)
print(f.read())
finaly:
F.close()
可以用
with。open()as. F: f是enter方法后边的值会复制给f
print(f.read())
46、app是appcontent的一个属性,核心对象只有一个,app = create_app是主线程来实现的,后边启用的是子线程,request是每启动一个线程都会执行一次,会创建好多个请求对象
线程隔离是字典健是线程id号,不同线程操作同一个全局对象都是会有相互影响的,
全局计数器
id为key的字典—local(用点操作)——localstack(用pop,push操作)
appcontext和requestcontext——请求开始进入localstack()栈结构,请求结束pop出去
flask—appcontext (flask是一个属性) request—request context(request是一个属性)
current_app —指向localstack的栈顶元素localstack.top=appcontext top.app==flask
request同理
47、wsgi:
两个参数:1 environ是一个字典对象,包含cgi风格的环境变量
2 start_response参数是一个接受两个固定参数和一个可选参数的可调用者
wsgi服务器是为每一个客户端的请求调用wsgi应用
wsgi应用:用server运行它。 wsgiref.simple_server import make_server
Https = make_server(0.0.0.0,8000,application)
服务系统:centos
Wsgi服务器:gunicore(安装使用、配置简单、消耗内存比较少、搭配底层网络库性能好、) gevent(并发好,用携程实现,性能好)
web服务器:nginx服务器(内存少,性能高)
部署方案设计:
部署工具的使用:supervisor进程管理工具 1、应用程序进程的控制,类似于管理应用程序 2、多应用进程的管理(管理多个进程)3、应用终端后的快速回复(自动重启应用程序)
cd. /etc/supervisor/
Vim supervisors.conf 在另一个配置文件下创建应用app的配置文件
启动:sudo service. Supervisor start
进入控制台: sudo. Supervisorctl
停止:Stop app status. Start. App. 在访问:curl. 127.0.0.1:8080 clear退出
48、第三方登录逻辑:
49、unique(唯一,就是比如可以有同年同月同日生的人),nuable(可以为空),index=true(可以索引,润许索引,一般是时间,因为可以按照时间进行排序)
def __repr__(self) 打印一个对象以友好按照__repr__自己定义的方式显示(面向程序员)
Return “
Def __str__ (self): 打印一个实例对象调用__str__ 方法(面向用户)
Return
50、mystr="hello python\n" #repr可以观察转义字符,不会翻译转义字符
print(str(mystr)) #人可以可以看懂
print(repr(mystr))
有__call__方法时实例对象是可以调用的(可以传入参数)!!!!!所有的函数都是可调用
对象
在Python中,函数其实是一个对象:
>>> f = abs
>>> f.__name__
'abs'
>>> f(-123)
123
由于 f 可以被调用,所以,f 被称为可调用对象。
51、需要改动模型、表单验证、表单对应的html模版、、、把对应的表单和db对象导入到对应的views函数中,db导入model里面去创造模型,导入views里面来操作模型、
form = loginform()
Request.form[“user_name”]
Db.session(在插入和删除的时候用),User(在查询的时候使用)
Def check_pwd(self.pwd): 检查登录密码是否正确
Return. Self.pwd == pwd
52、first_or_404代表如果有错误就会抛出404错误,停止程序的运行。
flask_sqlalchemy中写的是model.query还是写db.session.query来查询数据
登录逻辑:先查看用户名是否存在,在查看密码对不对,可以闪现消息
退出逻辑:session.pop(). redirect(url_for())
注册逻辑:
判断是get还是post请求,在进行表单验证
首先:查看用户名是否存在query_user_by_name()。 不能用first_or_404,不能直接抛出错误页面,而是告诉用户重新输入用户信息。
然后:用户不存在,执行注册逻辑。用户图像麻烦点(判断图像扩展名对不对)
53、装饰器控制登录是当用户进来时装饰器会检查一下session中是否存在user_name
54、删除用户操作:
user= user.query.filter_by(name=session.get(“user_name”).first()
db.session.delete(user)
db.session.commit()
55、db.session.add(). 这个操作既可以是更新也可以是创建的操作,前提都是要检查一下是否有这个东西!!!!!更新完事后再把以前的sesson.pop()掉
user.query.filter_by(name=session.get(user_name)) 这个查找要指明是哪个字段,name字段!!!修改完成后就要回填表单form=form render_template(“user_info.html”,user=user,form=form)
56、在返回渲染模版的时候渲染初始值textarea这种富文本类型的时候失败解决办法:在request的get请求中拿到查找的数据。重新赋值回填表单
if request.method == “get”:
form.user_jianjie.data = user.jianjie
用户登录成功的时候记录下session信息
查询用户时尽量用主键用户id来查找!!!!
57、
except Exception as e:
current_app.logger.exception(e)
db.session.rollback()
ret = {
'errcode': 5,
'errmsg': e.args,
}
print(ret)
return jsonify(ret)
params = {
'op_mod': data.get('op_mod', None),
'related_id': int(data['related_id']) if data['related_id'] else None,
'op_interface': data.get('op_interface', None),
}
params = {k:params[k] for k in params.keys() if params[k] is not None}
58、0802156d441b
59、 [[1, 2, 3], [4, 5, 6], [7, 8, 9]] #可以看出,tolist()将矩阵a转换为一个以列表为元素的列表。 60、项目总结:重要
大json中只要有一层嵌套就封装一层函数接口,只要一层有多个列表就是一个for循环!!
for循环中每一个对象用to_dict方法进行数据data获取,然后在添加额外的字段,如果额外的字段是一个嵌套的结构,那么就会增加一个函数API接口进行获取嵌套列表中的内容!!然后在整体把data给append进到data_list中去,然后在添加到最外层中。如果到最底层就直接通过列表生成式把结果显示出来,就可以不用for循环了,其实也就相当于利用了for循环了
61、@lm.user_loader。 把user_id设置到session中
@lm.request_loader 定制登录授权信息比如token
@lm.unauthorized_handler. 未登录访问需要登录的页面定制输出信息
62、alembic revision --autogenerate -m"回单卡号、回单查询密码"
63、一般返回结果时要是增删改的内容都是自己封装的状态码和状态信息errcode和errmsg等内容!!!!
64、margin 这是外边的距离,padding是内部的距离
65、
sudo easy_install fabric
[ken@~$] which fab
/usr/local/bin/fab
66、python发短息的时候要加一个消息队列!
67、markdown和有道云同步!!
68、ujson和json,用json给移动端传递空字典的时候可能会转换成为【】list但是用ujson就不会!
69、system_bp系统的相关设置: