1.sqlalchemy
不自带表更新,官方的迁移工具主要是 alembic
和sqlalchemy migrate
, 如果不使用工具,创建新表可以更新model后通过sqlalchemy
的create_all
方法,修改表字段则只能进数据库手动改,同时更新model。
另外, sqlite在shell
下执行sql
脚本的方式是:sqlite my.db < test.sql
(在客户端命令行中,是:.read test.sql
)
2.flask
引用配置文件时,有几种方法,参考链接:https://zhuanlan.zhihu.com/p/...
主要要注意的是配置文件中,配置项必须以大写形式,否则app.config
的几个读配置文件的方法(from_object, from_pyfile
等)都不会认小写的变量,官方文档说明如下: The configuration files themselves are actual Python files. Only values in uppercase are actually stored in the config object later on. So make sure to use uppercase letters for your config keys.
3.jquery
的$(function () {})
写法,意思相当于$(document).ready(function())
,即文档加载完再执行。
摘:$(function () {})是$(document).ready(function())的简写,也相当于window.onload = function(){ }。虽然这段jquery代码与javascript代码在功能上可以互换,但执行的时间不一样,前者页面框架加载完成就执行,后者页面中所有内容加载完成才执行
4.有的系统(比如debian)默认用户的命令环境是sh
,而不是bash
,导致命令行用起来不正常。
打开/etc/passwd,看到比如root:x:0:0:root:/root:/bin/sh
,即定义root用户默认使用sh,而我们一般使用的是bash。改成/bin/bash
即可
改为bash后,‘#'号前面的文字有时候是:-bash-4.2#
,这个是由一个环境变量PS1
决定的。这种情况下执行一下echo $PS1
,输出是类似\s-\v\$
要显示成常见的类似[user@localhost ~]
状态,可以改为[\u@\h \w]\$
。
5.几个技术名词:
`raid -> disk`
`ipvs -> host (loadbalancing)`
`vrrp -> router (high-ability)`
`bond -> network card`
`(lvs = ipvs + vrrp)`
简单理解:
raid就是把几块硬盘连在一起,达到提高存储稳定性的效果,对存储者来说像是一块硬盘。
ipvs就是把几台服务器主机合在一起,主要用于负载均衡,对客户端访问者来说像是一台服务器。
vrrp就是多个路由器合在一起,主要用于高可用,对主机来说就像是一个路由器。
bond就是多个网卡合在一起,既可用于高可用也可用于负载均衡,对主机来说就像是一张网卡。
其实无非是把多个对象对外表现为一个,实现负载均衡或者高可用。当然细节就比较复杂了。
6.debian
系下cron
默认使用run-parts
命令执行小时、天、周等定时,man
一下可知此命令用于执行一个文件夹内所有可执行文件,但是ln
了一个软链到/etc/cron.hourly
目录下发现并不会执行,手动执行run-parts
也确实没有输出,原来是因为run-parts
这个命令,对于带.sh后缀的不会执行…
7.sqlalchemy
报错:TypeError: an integer is required
,给boolean类型的字段赋了个字符串的值会出现这个报错。因为sqlite中boolean的值实际是用整型0和1记录(mysql中也一样,为tinyint类型).
8.关于flask
上下文:
之前用django
,习惯了进python命令行,class request():DATA={}
手动编一个请求,然后直接实例化view对象,调对应函数把request传进去即模拟了一次请求。
flask中请求并不直接作为参数传递到响应的函数中,而是作为一个上下文环境中的类似全局变量(好像不同于普通全局变量,待继续学习)。因此,在flask中要实现类似django那样命令行交互,需要些特殊处理,参考 http://flask.pocoo.org/docs/0...。
这里简单讲下流程: main.py是我的view文件,其中实例化了Flask对象(app),get_all
是其中一个响应请求的函数。
>>> from main.main import *
>>> d=app.test_request_context('shiki/?shiki=hahahahahaha')
>>> print(get_all().get_data())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "E:\workbench\flasksite\main\main.py", line 68, in get_all
db = get_db()
File "E:\workbench\flasksite\main\main.py", line 80, in get_db
if not hasattr(g, 'db'):
File "C:\Program Files\Python36\lib\site-packages\werkzeug\local.py", line 347, in __getattr__
return getattr(self._get_current_object(), name)
File "C:\Program Files\Python36\lib\site-packages\werkzeug\local.py", line 306, in _get_current_object
return self.__local()
File "C:\Program Files\Python36\lib\site-packages\flask\globals.py", line 44, in _lookup_app_object
raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in a way. To solve
this set up an application context with app.app_context(). See the
documentation for more information.
>>> d.push()
>>> print(get_all().get_data())
b'[\n "hahahahahaha"\n]\n'
>>>
可以看到直接执行get_all是会提示Working outside of application context
。创建一个test_request_context
对象,传入url作为参数,并执行push,就相当于进入了上下文环境,可以执行了。d.pop
可退出上下文环境。
ps:看起来比起用postman好像毫无优势,不过有时候就是双手不想离开键盘… (:з」∠)
9.python2, 标准库urllib(2)和三方库requests的差别
一图流……
10.关于nfs配置
no_root_squash:登入 NFS 主机使用分享目录的使用者,如果是 root 的话,那么对于这个分享的目录来说,他就具有 root 的权限!这个项目『极不安全』,不建议使用!
root_squash:在登入 NFS 主机使用分享之目录的使用者如果是 root 时,那么这个使用者的权限将被压缩成为匿名使用者,通常他的 UID 与 GID 都会变成 nfsnobody 那个系统账号的身份。
11.关于原生django(2.0.4)
和rest_framework
在rest_framework
中,封装了data
属性,可以由这个统一接口拿到不同请求类型的数据。官方文档如下:
request.data
returns the parsed content of the request body. This is
similar to the standard request.POST and request.FILES attributes
except that:· It includes all parsed content, including file and non-file inputs.
· It supports parsing the content of HTTP methods other than POST,
meaning that you can access the content of PUT and PATCH requests.
· It supports REST framework's flexible request parsing, rather than
just supporting form data. For example you can handle incoming JSON
data in the same way that you handle incoming form data.
在django
中,request
对象有request.GET
和request.POST
方法分别用于获取数据,但POST
不能获取application/json
类型的请求体。
json数据只能在request.body
属性中拿到,是一个bytes
类型(python3),需要json.loads
转为字典。
没有一个像rest_framework
那样的统一接口拿各种请求类型的数据。如果要做到那样,一种解决办法是和前端约定请求体全部用json,然后写个中间件。类似:
try:
request.DATA = json.loads(request.body)
except json.decoder.JSONDecodeError:
xxx
注意中间件不应该去访问request.POST
.Accessing request.POST inside middleware before the view runs or in process_view() will prevent any view running after the middleware from being able to modify the upload handlers for the request, and should normally be avoided.
当然也可以get和post明确各自用,json再另外一个接口,关于这一点好像没有找到风格指南。直觉来说肯定是统一接口方便。
我的情况是公司原本项目用了rest_framework
,而我最近的任务要撸个独立的系统,我打算纯用django。关于我们为什么要使用rest_framework
,见:
When should i use django-rest-framework?
11.关于gevent.subprocess.Popen
gevent.subprocess.Popen
使用数组作为参数(shell=False)
时元素必须都为字符串类型,否则会抛出异常--- execv() arg 2 must contain only strings
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。